【问题标题】:Python program still running but PID can't be foundPython程序仍在运行但找不到PID
【发布时间】:2018-12-15 11:17:18
【问题描述】:

我正在后台运行一个与父程序分离的子程序。在我退出父程序后,我希望子程序继续运行并登录到OUTPUT_PATH。事实上,我可以看到日志文件正在更新。然而,当我试图从ps aux 中找到 PID 时,我找不到它。谁能解释这种行为?我做错了什么?

 shellCommand = "nohup python PYTHON_PROGRAM ARGS >OUTPUT_PATH 2>&1 &" 
 subprocess.Popen(shellCommand, shell=True, preexec_fn=os.setpgrp) 

【问题讨论】:

  • 您确定您只是没有错过吗?我试过你的剪报,对我来说PYTHON_PROGRAMrunner.py。当我运行ps -fwp $(pgrep -f runner.py) 时,我看到了这个过程。难道只是它不在列表的底部或容易发现的地方吗?我还应该提到这是派生后台进程的一种非正统方式。 ;)
  • 首先,非常感谢!这很奇怪......我使用的是子进程模块返回的 PID,它返回 15789,运行命令的 PID 是 15790。你知道这种差异的原因吗?另外你能详细说明什么是更正统的方法吗?
  • 你使用shell=True,这意味着python创建了一个shell进程,并且该shell在另一个进程中执行命令

标签: python subprocess pid nohup


【解决方案1】:

好的,这对 cme​​ts 来说太大了。通过运行ps -fwp $(pgrep -f PYTHON_PROGRAM),我们现在已经找到了该进程。 :) 但它的 PID 与Popen.pid 报告的不匹配。这将取决于您使用shell=True 后调用的shell 实例。第一个fork 是调用shell,第二个是你的脚本。实际上,这在上面提到的链接中有记录:

请注意,如果您将 shell 参数设置为 True,则这是生成的 shell 的进程 ID。

但请参阅下面的注释。

这将我们带到“更正统的方式”。我们正在进入可能有争议的领域,不同的人,不同的想法。第一个可能不像documentation 那样建议不要使用shell=True,除非你真的需要。

args 是所有调用所必需的,并且应该是一个字符串,或一系列程序参数。提供一系列参数通常是首选,因为它允许模块处理任何所需的参数转义和引用(例如,允许文件名中的空格)。如果传递单个字符串,shell 必须为 True(见下文),否则字符串必须简单地命名要执行的程序而不指定任何参数。

还有另一部分是关于不听建议的(安全)影响。

因此,编译参数列表以使用您的脚本运行 nohup 并通过 Popen 的关键字参数(stdoutstderr)处理输出重定向似乎是一个很好的做法,并且会还可以为您提供一致的 PID。

这最后一步可能会引起最大的争议:但您实际上可以通过 python 接口对相应的系统调用进行守护进程。有据可查的例子似乎在github 中增长(从下面提到的 PEP 中的链接到达一跳以上)。

或者有一个library 引用自该主题的PEP-3143


注意:该位似乎并不总是正确的(调用 sh 是,但两个 PID 不是)。至少在我的系统上,我观察到 shexec 的程序通过 -c (本身)调用而没有分叉。从几次快速运行和跟踪来看,至少如果我没有弄乱 stdin/-out/-err(即没有管道或重定向)、没有强制子 shell (...) 或没有在@987654340 上链接命令,情况就是这样@。 (后两者很明显,一旦您意识到如何实现重定向,前两者也是如此)。所以至少对于我的外壳,我敢于推断并说:它似乎不会分叉,除非它必须。或者更简化(因此不完全正确)的说法是:简单的东西不会分叉。

【讨论】:

    猜你喜欢
    • 2020-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 2023-02-08
    相关资源
    最近更新 更多