我正在做一些需要使用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
,它不会停下来让我输入一些东西。
有什么建议吗?
最佳答案
当你用 |
管道时,您正在将第一个命令的输出重定向到第二个命令的输入。这意味着第二个命令的标准输入没有连接到终端,因此无法读取键盘输入。表格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
这里我用了()
创建一个子 shell,其中使用 3<&0
在文件描述符 3 上复制标准输入,以及在管道中生成的脚本都将其重命名为带有 exec <&3 3<&-
的标准输入和 exit
s 以防止从恢复的标准输入中读取更多命令。这有副作用,例如描述符 3 为 echo
打开命令。
因为使用的主要原因curl address | bash
首先是保持命令简单,这不是你想要的。此外,如果下载过程中出现任何问题,管道会阻止您进行处理;您的脚本可能在任何地方被打断。传统的下载然后运行并没有那么糟糕:
curl -O http://somewhere/somefile.py && python somefile.py
相比之下,这节省了 somefile.py
到你的文件系统。这也有缺点,比如需要一个可写的文件系统并替换那个特定的文件名。从好的方面来说,如果出现任何问题,它会停在那里并且不会运行损坏的脚本,因为 &&
.
如果您正在下载的脚本适合命令行,最后一种可能性是将它放在那里而不是管道中:
python -c "$(curl $url)"
这对中断下载具有相同的弱点,另外将脚本内容放在通常是公共(public)信息的命令行中(考虑 ps ax
输出)。但是,如果您只是使用 curl 下载脚本,那么有关如何获取它的信息也可能如此。由于这不会重定向标准输入,因此它可能是您当前问题的答案。
一般来说,我建议不要在未经验证的情况下直接从互联网上运行任何脚本 curl something | bash
命令行可以。它太容易被劫持,因为任何步骤都不涉及验证。最好使用检查签名的软件包存储库,例如 apt。
在 Linux 上访问终端的另一种方法是通过设备 /dev/tty
.此方法用于实例 when ssh
asks for a password .也可以重新打开 stdout 或 stderr 进行输入,如 ( exec < /dev/null ; read foo <&2 ; echo $foo )
.
关于python - 使用 sys.stdin.readline() 通过 "| bash "运行 python 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43292352/