Python 生成子进程、分离并退出

发布于 2024-11-03 03:52:02 字数 598 浏览 1 评论 0原文

我想知道这是否是执行系统进程并与父进程分离的正确方法,尽管允许父进程退出而不创建僵尸和/或杀死子进程。我目前正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

说好的呢 2024-11-10 03:52:02

对于 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 系统(即 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:

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, i.e. Linux, MacOS, etc.

Tested on Python 3.8.1 on macOS 10.15.5

缱倦旧时光 2024-11-10 03:52:02

Unix 上的 popen使用 fork。这意味着您可以安全地执行以下操作:

  1. 在父进程中运行 Popen
  2. 立即退出父进程

当父进程退出时,子进程将由 init 进程继承(在 OSX 上launchd)并且仍将在后台运行。

python 程序的前两行不是必需的,这完全可以工作:

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

我正在阅读有关双叉的内容,不确定这是否有必要

如果您的父进程继续运行并且您需要保护您的孩子免于与父进程一起死亡,则需要这样做。 这个答案展示了如何做到这一点。

双分叉的工作原理:

  1. 通过 os.fork() 创建一个子进程
  2. ,在此子进程中调用 Popen() 启动长时间运行的进程
  3. 退出子进程:Popen进程被init继承并在后台运行

为什么家长必须立即退出?如果不立即退出会发生什么?

如果您让父进程保持运行并且用户停止进程,例如通过 ctrl-C (SIGINT) 或 ctrl-\ (SIGQUIT),然后它会杀死父进程和 Popen 进程。

如果分叉后一秒退出怎么办?

然后,在这 1 秒期间,您的 Popen 进程很容易受到 ctrl-c 等攻击。如果您需要 100% 确定,则使用双分叉。

popen on Unix is done using fork. That means you'll be safe with:

  1. you run Popen in your parent process
  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.

The first two lines of your python program are not needed, this perfectly works:

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()
  2. in this child call Popen() which launches the long running process
  3. exit child: Popen process is inherited by init and runs in the background

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 e.g. via ctrl-C (SIGINT) or ctrl-\ (SIGQUIT) then it would kill both the parent process and the Popen process.

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.

⒈起吃苦の倖褔 2024-11-10 03:52:02

Windows 上的解决方法:

    proc_exe = subprocess.Popen(<Your executable path>, shell=True)
    proc_exe.send_signal(subprocess.signal.SIGTERM)

subprocess.Popen() 的默认父进程将是调用者进程;通常这是一个很好的功能;但在某些情况下,父进程(调用者)的资源将被锁定,直到子进程终止。 subprocess.send_signal() 方法可以解决这个问题。
运行该命令后,子进程()与父进程断开连接,以进程的形式自行运行。

确保使用“shell=True”选项来调用子进程。

因为 send_signal() 方法只会终止“CMD.exe”(父进程)而不是实际的调用者。

Work around on Windows:

    proc_exe = subprocess.Popen(<Your executable path>, shell=True)
    proc_exe.send_signal(subprocess.signal.SIGTERM)

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.
淡淡離愁欲言轉身 2024-11-10 03:52:02

注意:这是适用于 Windows 的解决方案。不是 Linux。

我与 Windows 进行了斗争,以在退出 python 脚本时运行批处理文件(又名:从 python 脚本中分离子批处理进程)。

从Python 3.7开始,您可以使用非常简单的 DETACH_PROCESS 标志此标志是 Windows 特定的!

import subprocess
import sys
process_handler = subprocess.Popen('C:\\test\\test_batch.bat', creationflags=subprocess.DETACHED_PROCESS)
sys.exit(0)

并且批处理文件在 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!

import subprocess
import sys
process_handler = subprocess.Popen('C:\\test\\test_batch.bat', creationflags=subprocess.DETACHED_PROCESS)
sys.exit(0)

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文