45

我试过运行这样的东西:

subprocess.Popen(['nohup', 'my_command'],
                 stdout=open('/dev/null', 'w'),
                 stderr=open('logfile.log', 'a'))

如果父脚本正常退出,则此方法有效,但如果我终止脚本(Ctrl-C),我的所有子进程也会被终止。有没有办法避免这种情况?

我关心的平台是 OS X 和 Linux,使用 Python 2.6Python 2.7。

4

5 回答 5

62

子进程接收与SIGINT您的父进程相同的信息,因为它位于同一进程组中。您可以通过调用子进程将子进程放入自己的进程组os.setpgrp()中。Popenpreexec_fn论点在这里很有用:

subprocess.Popen(['nohup', 'my_command'],
                 stdout=open('/dev/null', 'w'),
                 stderr=open('logfile.log', 'a'),
                 preexec_fn=os.setpgrp
                 )

preexec_fn仅适用于 un*x-oids。Windows " creationflags=CREATE_NEW_PROCESS_GROUP" 似乎有一个粗略的等价物,但我从未尝试过。)

于 2013-06-04T22:26:57.047 回答
31

The usual way to do this on Unix systems is to fork and exit if you're the parent. Have a look at os.fork() .

Here's a function that does the job:

def spawnDaemon(func):
    # do the UNIX double-fork magic, see Stevens' "Advanced 
    # Programming in the UNIX Environment" for details (ISBN 0201563177)
    try: 
        pid = os.fork() 
        if pid > 0:
            # parent process, return and keep running
            return
    except OSError, e:
        print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1)

    os.setsid()

    # do second fork
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit from second parent
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1)

    # do stuff
    func()

    # all done
    os._exit(os.EX_OK)
于 2011-05-15T21:14:44.823 回答
6

经过一个小时的各种尝试,这对我有用:

process = subprocess.Popen(["someprocess"], creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP)

这是windows的解决方案。

于 2020-08-01T18:01:57.473 回答
1

从 3.2 开始,您还可以使用start_new_session标志(仅限 POSIX)。

import subprocess

p = subprocess.Popen(["sleep", "60"], start_new_session=True)
ret = p.wait()

请参阅Popen 构造函数中的 start_new_session

于 2020-11-02T15:57:45.753 回答
-1
with open('/dev/null', 'w') as stdout, open('logfile.log', 'a') as stderr:
    subprocess.Popen(['my', 'command'], stdout=stdout, stderr=stderr)

类 subprocess.Popen(...)

在新进程中执行子程序。在 POSIX 上,该类使用类似 os.execvp() 的行为来执行子程序。在 Windows 上,该类使用 Windows CreateProcess() 函数。

os.execvpe(文件,参数,环境)

这些函数都执行一个新程序,替换当前进程;他们不回来。在 Unix 上,新的可执行文件被加载到当前进程中,并且将具有与调用者相同的进程 ID。错误将报告为 OSError 异常。

于 2020-03-03T19:51:33.910 回答