python - 使用 sys.stdin.readline() 通过 "| bash "运行 python 脚本

标签 python linux bash shell

我正在做一些需要使用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/

相关文章:

linux - 用于在路径中查找脚本并启动另一个脚本的 Bash 脚本

python - 在Python中使用装饰器函数时,如何获取包装器函数返回的信息?

python - 不选择缺失值吗?

python - 如何从字符串列表中删除连字符

python - 在 Centos 5 上使用非系统 Openssl 编译 Python 2.7.12

linux - 在单个 bsub 命令中应用 Bourne shell 背景符号

bash - 如何限制 bash 函数中使用的线程/子进程数

python - 为什么tensordot/reshape与kron不一致?

linux - 在 shell 脚本中编辑 sudo 文件

python - 在 python/bash 中打印带有条件的特定范围的行