python - 为什么 subprocess.Popen 返回码与 bash 的类似命令不同

标签 python bash subprocess dash-shell

为什么

import subprocess

p = subprocess.Popen(["/bin/bash", "-c", "timeout -s KILL 1 sleep 5 2>/dev/null"])
p.wait()
print(p.returncode)

返回

[stderr:] /bin/bash: line 1: 963663 Killed                  timeout -s KILL 1 sleep 5 2> /dev/null
[stdout:] 137

什么时候

import subprocess

p = subprocess.Popen(["/bin/bash", "-c", "timeout -s KILL 1 sleep 5"])
p.wait()
print(p.returncode)

返回

[stdout:] -9

如果将 bash 更改为 dash,在这两种情况下都会得到 137。我知道 -9 是 KILL 代码而 137 是 128 + 9。但是对于类似的代码获得不同的返回码似乎很奇怪。

出现在 Python 2.7.12 和 python 3.4.3

看起来 Popen.wait() 没有调用 Popen._handle_exitstatus https://github.com/python/cpython/blob/3.4/Lib/subprocess.py#L1468当使用 /bin/bash 但我不知道为什么。

最佳答案

这是因为 bash执行 timeout有或没有重定向/管道或任何其他 bash 功能:

  • 带重定向

    1. python开始bash
    2. bash开始timeout ,监控流程并进行管道处理。
    3. timeout将自己转移到一个新的进程组并启动sleep
    4. 一秒钟后,timeout发送 SIGKILL进入其过程组
    5. 随着进程组死亡,bash从等待返回 timeout , 看到 SIGKILL并将上面粘贴的消息打印到 stderr .然后它将自己的退出状态设置为 128+9(timeout 模拟的行为)。
  • 没有重定向

    1. python开始bash .
    2. bash看到它自己无事可做并调用execve()有效地用 timeout 替换自己.
    3. timeout如上所述,整个过程组以SIGKILL结束.
    4. python获得 9 的退出状态并进行一些处理将其变成 -9 ( SIGKILL )

换句话说,没有重定向/管道/等。 bash从调用链中退出。你的第二个例子看起来像 subprocess.Popen()正在执行 bash ,但实际上并没有。 bashtimeout 时不再存在做它的事,这就是为什么你没有收到任何消息和未损坏的退出状态。

如果您想要一致的行为,请使用 timeout --foreground ;在这两种情况下,您都会获得 124 的退出状态。

我不知道破折号;然而假设它不做任何execve()用它正在执行的唯一程序有效地替换自己的诡计。因此,您总是会在破折号中看到 128+9 的损坏退出状态。

更新:zsh表现出相同的行为,而即使是简单的重定向,如 timeout -s KILL 1 sleep 5 >/tmp/foo,它也会消失等等,给你一个 -9 的退出状态。 timeout -s KILL 1 sleep 5 && echo $?将在 zsh 中为您提供状态 137还有。

关于python - 为什么 subprocess.Popen 返回码与 bash 的类似命令不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45824955/

相关文章:

linux - 如何使用 sed 在字符串匹配后附加带有美元符号的变量?

python - 从 python 执行 .jar 文件

javascript - Python 和 Javascript 正则表达式有什么不同?

python - 如何替换Excel中的字符串并检查整个单元格字符串?

Python - 将符号表达式(sympy)写入txt文件

bash - “moveToLocal: Option ' -moveToLocal'尚未执行什么操作。”手段?

linux - 对文本 Bash Linux 中的特定列使用 grep

python-在多个文件上运行脚本

python - 使用 python 子进程检查 pip 是否安装在 Windows 上

python - Selenium 点击的视觉反馈