【问题标题】:Correctly getting return code when issuing command over SSH via subprocess通过子进程通过 SSH 发出命令时正确获取返回码
【发布时间】:2015-05-16 09:17:47
【问题描述】:

我正在尝试通过 ssh 发出命令并通过子进程获取其返回码。我有一些看起来像这样的代码:

cmd = 'ssh user@ip_addr "some_command"'
res = subprocess.check_output(
    cmd,
    shell=True,
    stdout=subprocess.PIPE)

现在,如果 cmd 只生成退出代码(例如,将 cmd 设置为“exit 1”,然后执行 try/catch 以查看它是否以非零退出。但是,以下挂起无限期:

cmd = 'ssh user@ip_addr "ls -la && exit 0;"'
res = subprocess.check_output(
    cmd,
    shell=True,
    stdout=subprocess.PIPE)

我看到two questions 那个looked similar 和我did RTFM,但我仍然不知道该怎么办。我真的不在乎命令是否生成输出;我更关心退出代码。如果有人知道这样做的最佳方法是什么,或者我是否不恰当地使用子流程,我将不胜感激。

【问题讨论】:

  • check_output 似乎没有 stdout 参数。你的意思是stderr吗?
  • 我做到了,对此感到抱歉。
  • 那么你需要看到关于 not 使用stderr=PIPE 的重要通知,因为它可能会挂在你指向的链接上。
  • 你有没有机会在 ssh 可能一直在等待你的密码的不同环境中运行第二个命令?

标签: python shell ssh subprocess


【解决方案1】:

删除stdout=subprocess.PIPE,它应该可以工作; check_output 本身会捕获输出,因此使用 stdout=subprocess.PIPE 重定向它会导致问题。如果您根本不关心输出,只需使用subprocess.check_call(同样,不要使用stdout=subprocess.PIPE)。

【讨论】:

  • stdout=PIPE 与问题中描述的行为不符。 stdout=PIPE 导致立即 ValueError,而不是“以下无限期挂起”——OP 没有向我们展示实际代码。如果它是stderr=PIPE,那么如果进程填充了它的stderr OS 管道缓冲区(在我的机器上约为65K,例如call(['python3', '-c', 'import sys; print("a"*10**4, file=sys.stderr)'], stderr=PIPE) 不会挂起),它可能会挂起。我看不到 ls -la 如何在 stderr 上生成 ~65K 错误消息。
【解决方案2】:

请勿使用std{out,err}=PIPE,除非您从管道中读取!!!

丢弃使用subprocess模块通过ssh发出的命令输出时获取返回码:

from subprocess import call, DEVNULL, STDOUT

returncode = call(['ssh', 'user@ip', 'ls -la && exit 0;'],
                  stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT)

另请参阅,How to hide output of subprocess in Python 2.7

注意:shell=True 未使用。

【讨论】:

    猜你喜欢
    • 2015-08-08
    • 2016-10-08
    • 1970-01-01
    • 2023-03-20
    • 2021-02-25
    • 2020-01-13
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多