繁体   English   中英

通过“ |运行python脚本 bash”与sys.stdin.readline()

[英]Running python script by “ | bash ” with sys.stdin.readline()

我在做某事需要使用curl xxx | bash curl xxx | bash运行某些东西。 我使用sys.stdin.readline()创建了一个python脚本来进行如下测试:

[python3] test.py


import sys
def read_input():
    input = sys.stdin.readline().rstrip()
    print(input)
read_input()

它可以直接由python3 test.py运行

test
test

但是,如果我使用echo 'python3 test.py' | bash echo 'python3 test.py' | bash ,它不会停止让我输入一些信息。

有小费吗?

当您使用| ,您正在将第一个命令的输出重定向到第二个命令的输入。 这意味着第二条命令的标准输入未连接到终端,因此无法读取键盘输入。 表单curl xxx | bash 因此, curl xxx | bash仅适用于非交互式脚本。 这绝不是Python特有的。

原则上,您可以通过将输入描述符保存在另一个数字下来解决此问题,但这确实变得很复杂:

$ ( echo 'exec <&3 3<&- ; echo script starts ; read hello ; echo you entered $hello ; exit' | bash ) 3<&0
script starts
something
you entered something

在这里,我使用()创建了一个子外壳,其中stdin使用3<&0复制到文件描述符3上,并且管道中生成的脚本都使用exec <&3 3<&-将其重命名为stdin并exit s以防止从还原的标准输入中读取更多命令。 这具有副作用,例如为echo命令打开了描述符3。

既然使用curl address | bash主要原因 curl address | bash首先是保持命令简单,这不是您要执行的操作。 此外,管道可以防止您在下载过程中出现任何问题。 您的脚本可能在任何地方被打断。 然后进行传统下载并没有那么糟糕:

curl -O http://somewhere/somefile.py && python somefile.py

相比之下,这会将somefile.py保存到您的文件系统中。 这样做有缺点,例如需要可写文件系统并替换该特定文件名。 从好的方面来看,由于&& ,如果出现任何问题,它将停止在该位置并且不会运行损坏的脚本。

如果您要下载的脚本适合命令行,则最后一种可能是将其放在此处而不是放在管道中:

python -c "$(curl $url)"

这与中断下载具有相同的弱点,并且另外将脚本内容放置在通常是公共信息的命令行中(请考虑ps ax输出)。 但是,如果您只是使用curl下载脚本,那么有关如何获得该脚本的信息也是。 由于这不会重定向stdin,因此它可能是您当前问题的答案。

通常,我建议不要在未经验证的情况下直接在Internet上运行任何脚本,因为这会使curl something | bash curl something | bash命令行可以。 这很容易被劫持,因为任何步骤都不需要进行验证。 最好使用检查签名之类的软件包存储库,例如apt。

在Linux上访问终端的另一种方法是通过/dev/tty设备。 例如, ssh要求输入密码时,使用此方法。 也可能重新打开stdout或stderr进行输入,如( exec < /dev/null ; read foo <&2 ; echo $foo )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM