正确使用 subprocess.Popen 通过 SSH 发出命令

Correct use of subprocess.Popen to issue a command via SSH

其他帖子也涉及到这个主题,但我仍然不清楚为什么会这样:

command = "echo /sbin/poweroff | ssh admin@" + address
shutcmd = subprocess.Popen(command, stdout = subprocess.PIPE, shell=True)

这行不通:

 shutcmd = subprocess.Popen(["echo", "/sbin/poweroff" "|" "ssh", "admin@",address], stdout = subprocess.PIPE, stderr = subprocess.PIPE)

你会如何正确地做到这一点?

您可以直接将命令传递给 运行 ssh,您不必通过管道输入它。

尝试

shutcmd = subprocess.Popen(['ssh', 'admin@' + address, '/sbin/poweroff'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

因为|是shell语法和语义。

您可以通过以下方式模拟:

from subprocess import Popen, PIPE, STDOUT

user = "root"
host = "1.2.3.4"

p = Popen(
    ["ssh", "{}@{}".format(user, host)],
    stdin=PIPE, stdout=PIPE, stderr=STDOUT
)
stdout, stderr = p.communicate("/sbin/poweroff\n")

然而,将命令本身作为 ssh:

的参数发出会更简单
p = Popen(
    ["ssh", "{}@{}".format(user, host), "/sbin/poweroff"],
)
p.wait()

顺便说一句;您的第一个示例之所以有效,是因为 shell=True。 shell 与 运行 你的 "piece of shell" 相关,因此生成的新 shell 有它自己的一组 fd 三元组,用于 stdin、stdout 和 stderr;所以 echo | ssh 工作。

参见:Pipeline (UNIX)