如何从 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.out
; stdout=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_fn
和 signal.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)))
我有一个简单的问题。我试图寻找解决方案,但没有任何答案可以解释我的需求。
问题是:
如何从 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.out
;stdout=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_fn
和signal.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)))