使用 subprocess.Popen() 从文件读取 ssh 输入

Reading input for ssh from a file, using subprocess.Popen()

我正在尝试调用一些我为远程服务器上的健康检查应用程序编写的本地 bash 脚本。

ssh -q <servername> "bash -s" -- < ./path/to/local/script.bash

以上从命令行运行得很好。但是,当我将调用包装在 python 中时,我不断收到错误消息:

bash: /path/to/file/script.bash: No such file or directory

至于我的python,我正在使用子流程模块。 Python:

bashcmd="ssh -q %s \"bash -s\" -- < ./%s" % (<server>,<bashfilepath>)
process=subprocess.Popen(bashcmd.split, stdout=subprocess.PIPE)
output, error = process.communicate()

如有任何帮助,我们将不胜感激!

第一个示例中的重定向是由 shell 完成的。 ssh 的标准输入从文件 ./path/to/local/script.bash 读取,ssh 传递给远程机器上的进程。

您不能使用 shell 重定向,因为您不是 运行 来自 shell 的命令。相反,您可以为 Popen() 使用 stdinstdout 参数来为您的进程设置标准输入和输出。您需要打开文件,然后将句柄传递给 stdin。解释如下:Using files as stdin and stdout for subprocess.

在 python 示例中,您将 ssh -q <server> "bash -s" -- < ./<filepath> 作为第一个参数传递给 subprocess.Popen(),除了参数列表或单个字符串:[=34= 的路径]可执行文件。您收到 No such file or directory 错误,因为您的字符串参数不是可执行文件的路径。遵循标准约定的正确格式为 subprocess.Popen(["/path/to/executable", "arg1", "arg2", ...]).

所有这些放在一起,您的示例应该类似于:

with open("./path/to/local/script.bash") as process_stdin:
    p = subprocess.Popen(["/usr/bin/ssh", "-q", server, "--", "bash", "-s"],
                         stdin=process_stdin, stdout=subprocess.PIPE)
    out, err = p.communicate()

这一切都在 subprocess module 的 Python 文档中进行了解释。