简体   繁体   English

Python 产生一个子子进程,分离并退出

[英]Python spawn off a child subprocess, detach, and exit

I'm wondering if this is the correct way to execute a system process and detach from parent, though allowing the parent to exit without creating a zombie and/or killing the child process.我想知道这是否是执行系统进程并与父进程分离的正确方法,尽管允许父进程退出而不创建僵尸和/或杀死子进程。 I'm currently using the subprocess module and doing this...我目前正在使用 subprocess 模块并执行此操作...

os.setsid() 
os.umask(0) 
p = subprocess.Popen(['nc', '-l', '8888'],
                     cwd=self.home,
                     stdout=subprocess.PIPE, 
                     stderr=subprocess.STDOUT)

os.setsid() changes the process group, which I believe is what lets the process continue running when it's parent exits, as it no longer belongs to the same process group. os.setsid() 改变了进程组,我相信这是当它的父进程退出时让进程继续运行的原因,因为它不再属于同一个进程组。

Is this correct and also is this a reliable way of performing this?这是正确的,也是执行此操作的可靠方法吗?

Basically, I have a remote control utility that communicate through sockets and allows to start processes remotely, but I have to ensure that if the remote control dies, the processes it started continue running unaffected.基本上,我有一个远程控制实用程序,它通过套接字进行通信并允许远程启动进程,但我必须确保如果远程控制死机,它启动的进程继续运行不受影响。

I was reading about double-forks and not sure if this is necessary and/or subprocess.POpen close_fds somehow takes care of that and all that's needed is to change the process group?我正在阅读有关双叉的信息,但不确定这是否有必要和/或 subprocess.POpen close_fds 以某种方式解决了这个问题,所需要的只是更改进程组?

Thanks.谢谢。

Ilya伊利亚

popen on Unix is done using fork . Unix 上的popen使用fork完成的 That means you'll be safe with:这意味着您将安全:

  1. you run Popen in your parent process你在你的父进程中运行Popen
  2. immediately exit the parent process立即退出父进程

When the parent process exits, the child process is inherited by the init process ( launchd on OSX) and will still run in the background.当父进程退出时,子进程由init进程(在 OSX 上launchd )继承,并且仍将在后台运行。

The first two lines of your python program are not needed, this perfectly works:不需要python程序的前两行,这非常有效:

import subprocess
p = subprocess.Popen(['nc', '-l', '8888'],
                     cwd="/",
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)

I was reading about double-forks and not sure if this is necessary我正在阅读有关双叉的信息,但不确定这是否有必要

This would be needed if your parent process keeps running and you need to protect your children from dying with the parent.如果您的父进程继续运行并且您需要保护您的孩子免于与父进程一起死亡,则需要这样做。 This answer shows how this can be done. 这个答案显示了如何做到这一点。

How the double-fork works:双叉的工作原理:

  1. create a child via os.fork()通过os.fork()创建一个孩子
  2. in this child call Popen() which launches the long running process在这个子调用Popen()中启动长时间运行的进程
  3. exit child: Popen process is inherited by init and runs in the background exit child: Popen进程由init继承并在后台运行

Why the parent has to immediately exit?为什么父母必须立即退出? What happens if it doesn't exit immediately?如果它没有立即退出会发生什么?

If you leave the parent running and the user stops the process eg via ctrl-C ( SIGINT ) or ctrl-\\ ( SIGQUIT ) then it would kill both the parent process and the Popen process.如果您让父进程保持运行并且用户停止进程,例如通过ctrl-C ( SIGINT ) 或ctrl-\\ ( SIGQUIT ) 那么它将杀死父进程和Popen进程。

What if it exits one second after forking?如果分叉后一秒退出怎么办?

Then, during this 1s period your Popen process is vulnerable to ctrl-c etc. If you need to be 100% sure then use the double forking.然后,在这 1 Popen期间,您的Popen进程容易受到 ctrl-c 等攻击。如果您需要 100% 确定,请使用双分叉。

For Python 3.8.x, the process is a bit different.对于 Python 3.8.x,过程有点不同。 Use the start_new_session parameter available since Python 3.2:使用自 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)

This will allow the parent process to exit while the child process continues to run.这将允许父进程退出而子进程继续运行。 Not sure about zombies.不知道僵尸。

The start_new_session parameter is supported on all POSIX systems, ie Linux, MacOS, etc.所有 POSIX 系统都支持start_new_session参数,即 Linux、MacOS 等。

Tested on Python 3.8.1 on macOS 10.15.5在 macOS 10.15.5 上的 Python 3.8.1 上测试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM