如何从 Python 脚本执行 运行 nohup 命令?

How to run nohup command from Python script?

我有一个简单的问题。我试图寻找解决方案,但没有任何答案可以解释我的需求。

问题是: 如何从 Python 启动 nohup 命令?基本上这个想法是,我有一个 Python 脚本来准备我的环境,我需要它用 nohup 命令启动多个脚本。我如何从 运行 Python 脚本中启动 nohup 命令,例如 nohup python3 my_script.py &,即使在我注销后也能使用该 nohup 命令 运行?

谢谢

你不需要 nohup -- 即使在 shell 中也不需要,在 Python 中更不需要。它执行以下操作:

  • 配置要忽略的 HUP 信号(很少相关:如果一个进程在 TTY 上没有句柄,无论如何它都不会在 TTY 退出时得到通知;shell 只将信号传播到 children 在交互模式下,而不是在 运行 脚本时)。
  • 如果 stdout 是一个终端,将它重定向到 nohup.out
  • 如果 stderr 是一个终端,将它重定向到已经重定向到 stdout 的任何地方。
  • 将标准输入重定向到 /dev/null

就是这样。没有理由使用 nohup 来做这些事情;没有它,它们都是微不足道的:

  • </dev/null 从 shell 中的 /dev/null 重定向标准输入; stdin=subprocess.DEVNULL 在 Python 中这样做。
  • >nohup.out 将标准输出重定向到 shell 中的 nohup.outstdout=open('nohup.out', 'w') 在 Python 中这样做。
  • 2>&1 使 stderr 与 shell 中的 stdout 转到相同的位置; stderr=subprocess.STDOUT 在 Python 中这样做。

因为您的进程没有通过上述重定向连接到终端,所以当该终端关闭时它不会隐式获得 HUP。但是,如果您担心信号被发送到 parent 的整个进程组,您可以通过将 child 拆分成一个单独的进程组来避免这种情况:

  • subprocess.Popen 参数 start_new_session=True 将 child 进程从 Python 中的 parent 拆分为一个单独的组,因此 parent整体发送到parent的进程组不会被child接收。
  • 添加 preexec_fnsignal.signal(signal.SIGHUP, signal.SIG_IGN) 更加明确,即 child 默认情况下应忽略 SIGHUP,即使收到 SIGHUP。

将所有这些放在一起可能看起来像(如果您确实希望日志转到名为 nohup.out 的文件——我建议选择一个更好的名称):

import subprocess, signal
subprocess.Popen(['python3', 'my_script.py'],
                 stdin=subprocess.DEVNULL,
                 stdout=open('nohup.out', 'w'),
                 stderr=subprocess.STDOUT,
                 start_new_session=True,
                 preexec_fn=(lambda: signal.signal(signal.NOHUP, signal.SIG_IGN)))