从python生成过程 [英] spawning process from python

查看:42
本文介绍了从python生成过程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从这样的网络应用程序中生成了一个长时间运行的脚本:

im spawning a script that runs for a long time from a web app like this:

os.spawnle(os.P_NOWAIT, "../bin/producenotify.py", "producenotify.py", "xx",os.environ)

脚本已成功生成并运行,但在它结束之前,我无法释放 Web 应用程序使用的端口,或者换句话说,我无法重新启动 Web 应用程序.我如何生成一个进程并使其完全独立于网络应用程序?

the script is spawned successfully and it runs, but till it gets over i am not able to free the port that is used by the web app, or in other words i am not able to restart the web app. how do i spawn off a process and make it completely independent of the web app?

这是在 linux 操作系统上.

this is on linux os.

推荐答案

正如@mark 阐明的那样,它是一个 Linux 系统,脚本可以很容易地使自己完全独立,即,一个守护进程,按照这个食谱.(您也可以在 os.fork 之后在父进程中执行此操作,然后只有 os.exec... 子进程).

As @mark clarified it's a Linux system, the script could easily make itself fully independent, i.e., a daemon, by following this recipe. (You could also do it in the parent after an os.fork and only then os.exec... the child process).

为了澄清@mark 对我的回答的评论的一些细节:按照食谱配方守护"进程不需要超级用户权限,也不需要更改当前工作目录(尽管配方中的代码确实做到了这一点,而且还有更多,这不是关键部分——而是 fork_exitsetsid 的正确逻辑序列电话).各种 os.exec... 变体 note 结尾使用父进程的环境,所以这部分也很简单——请参阅 Python 在线文档.

to clarify some details wrt @mark's comment on my answer: super-user privileges are not needed to "daemonize" a process as per the cookbook recipes, nor is there any need to change the current working directory (though the code in the recipe does do that and more, that's not the crucial part -- rather it's the proper logic sequence of fork, _exit and setsid calls). The various os.exec... variants that do not end in e use the parent process's environment, so that part is easy too -- see Python online docs.

为了解决在其他人的评论和答案中提出的建议:我相信 subprocessmultiprocessing 本身并没有守护子进程,这似乎是@mark需要;脚本可以自己完成,但是由于某些代码必须执行forks和setsid,我认为保留所有在该低级平面上生成,而不是在操作过程中混合一些高级和一些低级代码.

To address suggestions made in others' comments and answers: I believe subprocess and multiprocessing per se don't daemonize the child process, which seems to be what @mark needs; the script could do it for itself, but since some code has to be doing forks and setsid, it seems neater to me to keep all of the spawning on that low-level plane rather than mix some high-level and some low-level code in the course of the operation.

这是上述 URL 中配方的大幅精简和简化版本,专门为在父进程中调用以生成守护进程子进程而设计——这样,代码也可用于执行非 Python 可执行文件.正如给定的,代码应该满足@mark 解释的需求,当然它可以通过多种方式进行定制——我强烈建议阅读原始配方及其评论和讨论,以及它推荐的书籍,以获取更多信息.

Here's a vastly reduced and simplified version of the recipe at the above URL, tailored to be called in the parent to spawn a daemon child -- this way, the code can be used to execute non-Python executables just as well. As given, the code should meet the needs @mark explained, of course it can be tailored in many ways -- I strongly recommend reading the original recipe and its comments and discussions, as well as the books it recommends, for more information.

import os
import sys

def spawnDaemon(path_to_executable, *args)
    """Spawn a completely detached subprocess (i.e., a daemon).

    E.g. for mark:
    spawnDaemon("../bin/producenotify.py", "producenotify.py", "xx")
    """
    # fork the first time (to make a non-session-leader child process)
    try:
        pid = os.fork()
    except OSError, e:
        raise RuntimeError("1st fork failed: %s [%d]" % (e.strerror, e.errno))
    if pid != 0:
        # parent (calling) process is all done
        return

    # detach from controlling terminal (to make child a session-leader)
    os.setsid()
    try:
        pid = os.fork()
    except OSError, e:
        raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno))
        raise Exception, "%s [%d]" % (e.strerror, e.errno)
    if pid != 0:
        # child process is all done
        os._exit(0)

    # grandchild process now non-session-leader, detached from parent
    # grandchild process must now close all open files
    try:
        maxfd = os.sysconf("SC_OPEN_MAX")
    except (AttributeError, ValueError):
        maxfd = 1024

    for fd in range(maxfd):
        try:
           os.close(fd)
        except OSError: # ERROR, fd wasn't open to begin with (ignored)
           pass

    # redirect stdin, stdout and stderr to /dev/null
    os.open(os.devnull, os.O_RDWR)  # standard input (0)
    os.dup2(0, 1)
    os.dup2(0, 2)

    # and finally let's execute the executable for the daemon!
    try:
      os.execv(path_to_executable, args)
    except Exception, e:
      # oops, we're cut off from the world, let's just give up
      os._exit(255)

这篇关于从python生成过程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆