我想知道这是否是执行系统进程并与父进程分离的正确方法,尽管允许父进程退出而不创建僵尸和/或杀死子进程。我目前正在使用 subprocess 模块并执行此操作...
os.setsid()
os.umask(0)
p = subprocess.Popen(['nc', '-l', '8888'],
cwd=self.home,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
os.setsid() 更改进程组,我相信这就是让进程在父进程退出时继续运行的原因,因为它不再属于同一个进程组。
这是正确的吗?这也是执行此操作的可靠方法吗?
基本上,我有一个远程控制实用程序,它通过套接字进行通信并允许远程启动进程,但我必须确保如果远程控制死机,它启动的进程将继续运行而不受影响。
我正在阅读有关双分叉的内容,不确定这是否有必要和/或 subprocess.POpen close_fds 以某种方式解决这个问题,所需要做的就是更改进程组?
谢谢。
伊利亚
对于 Python 3.8.x,该过程有点不同。使用自 Python 3.2 起可用的
start_new_session
参数:
import shlex
import subprocess
cmd = "<full filepath plus arguments of child process>"
cmds = shlex.split(cmd)
p = subprocess.Popen(cmds, start_new_session=True)
这将允许父进程退出,而子进程继续运行。不确定僵尸。
所有 POSIX 系统都支持
start_new_session
参数,即 Linux、MacOS 等。
在 macOS 10.15.5 上的 Python 3.8.1 上测试
popen
是使用 fork
完成的。这意味着您将安全:
Popen
init
进程继承(OSX 上为
launchd
),并且仍会在后台运行。不需要 python 程序的前两行,这完全有效:
import subprocess
p = subprocess.Popen(['nc', '-l', '8888'],
cwd="/",
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
我正在阅读有关双叉的文章,不确定这是否有必要如果您的父进程继续运行并且您需要保护您的孩子不与父进程一起死亡,则需要这样做。
这个答案展示了如何做到这一点。
双叉工作原理:
os.fork()
创建一个孩子
Popen()
启动了长时间运行的进程
Popen
进程由
init
继承并在后台运行
为什么家长必须立即退出?如果不立即退出会怎样?如果您让父进程保持运行并且用户停止进程,例如通过
ctrl-C
(
SIGINT
) 或
ctrl-\
(
SIGQUIT
) 那么它会杀死父进程和
Popen
进程。
如果分叉后一秒退出怎么办?然后,在这 1 秒期间,您的
Popen
进程很容易受到 ctrl-c 等的攻击。如果您需要 100% 确定,则使用双分叉。
proc_exe = subprocess.Popen(<Your executable path>, shell=True)
proc_exe.send_signal(subprocess.signal.SIGTERM)
subprocess.Popen()的默认父进程将是调用者进程;通常这是一个很好的功能;但在某些情况下,父进程(调用者)的资源将被锁定,直到子进程终止。 subprocess.send_signal() 方法可以解决这个问题。
运行此命令后,子进程()与父进程断开连接,以进程的形式自行运行。确保使用“shell=True”选项来调用子进程。