Python 生成子进程、分离并退出
我想知道这是否是执行系统进程并与父进程分离的正确方法,尽管允许父进程退出而不创建僵尸和/或杀死子进程。我目前正在使用 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 以某种方式解决这个问题,所需要做的就是更改进程组?
谢谢。
伊利亚
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...
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.
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?
Thanks.
Ilya
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于 Python 3.8.x,该过程有点不同。使用自 Python 3.2 起可用的
start_new_session
参数:这将允许父进程退出,而子进程继续运行。不确定僵尸。
所有 POSIX 系统(即 Linux、MacOS 等)均支持
start_new_session
参数。已在 macOS 10.15.5 上的 Python 3.8.1 上测试
For Python 3.8.x, the process is a bit different. Use the
start_new_session
parameter available since Python 3.2: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, i.e. Linux, MacOS, etc.Tested on Python 3.8.1 on macOS 10.15.5
Unix 上的
popen
是使用fork
。这意味着您可以安全地执行以下操作:Popen
当父进程退出时,子进程将由
init
进程继承(在 OSX 上launchd
)并且仍将在后台运行。python 程序的前两行不是必需的,这完全可以工作:
如果您的父进程继续运行并且您需要保护您的孩子免于与父进程一起死亡,则需要这样做。 这个答案展示了如何做到这一点。
双分叉的工作原理:
os.fork()
创建一个子进程Popen()
启动长时间运行的进程Popen
进程被init
继承并在后台运行如果您让父进程保持运行并且用户停止进程,例如通过
ctrl-C
(SIGINT
) 或ctrl-\
(SIGQUIT
),然后它会杀死父进程和Popen
进程。然后,在这 1 秒期间,您的
Popen
进程很容易受到 ctrl-c 等攻击。如果您需要 100% 确定,则使用双分叉。popen
on Unix is done usingfork
. That means you'll be safe with:Popen
in your parent processWhen the parent process exits, the child process is inherited by the
init
process (launchd
on OSX) and will still run in the background.The first two lines of your python program are not needed, this perfectly works:
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:
os.fork()
Popen()
which launches the long running processPopen
process is inherited byinit
and runs in the backgroundIf you leave the parent running and the user stops the process e.g. via
ctrl-C
(SIGINT
) orctrl-\
(SIGQUIT
) then it would kill both the parent process and thePopen
process.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.Windows 上的解决方法:
subprocess.Popen() 的默认父进程将是调用者进程;通常这是一个很好的功能;但在某些情况下,父进程(调用者)的资源将被锁定,直到子进程终止。 subprocess.send_signal() 方法可以解决这个问题。
运行该命令后,子进程()与父进程断开连接,以进程的形式自行运行。
确保使用“shell=True”选项来调用子进程。
因为 send_signal() 方法只会终止“CMD.exe”(父进程)而不是实际的调用者。
Work around on Windows:
The default parent process of subprocess.Popen() will be the caller process; normally it is a good feature; but in some cases, the resources of the parent process (caller) will be locked until the sub process is terminated. The subprocess.send_signal() method will do the trick.
After running this command, the child process () disconnects from the parent process, running by itself as a process.
Make sure use the "shell=True" option to call up the child process.
Because the send_signal() method will just terminate the "CMD.exe" (the parent process) instead of the actual caller.
注意:这是适用于 Windows 的解决方案。不是 Linux。
我与 Windows 进行了斗争,以在退出 python 脚本时运行批处理文件(又名:从 python 脚本中分离子批处理进程)。
从Python 3.7开始,您可以使用非常简单的 DETACH_PROCESS 标志 。 此标志是 Windows 特定的!
并且批处理文件在 python 脚本可以退出时继续运行。
注意:默认情况下,
shell=False
。使用分离标志,您不需要设置
shell=True
Note: This is a solution for Windows. Not Linux.
Had my fight with Windows to get a batch file running while exiting the python script (aka: detach the child batch-process from the python script).
Since Python 3.7 you can use the very simple DETACH_PROCESS flag . This flag is Windows-specific!
And the batch file keeps running while the python script can exit.
Note: by default,
shell=False
.With the detach flag you do not need to set
shell=True