web-dev-qa-db-ja.com

Pythonからプログラムを実行し、スクリプトが強制終了された後も実行し続ける

私はこのようなものを実行しようとしました:

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

これは、親スクリプトが正常に終了した場合に機能しますが、スクリプトを強制終了(Ctrl-C)すると、すべての子プロセスも強制終了されます。これを回避する方法はありますか?

私が気にするプラットフォームはOS XとLinuxで、Python 2.6 and Python 2.7。

36
James

Unixシステムでこれを行う通常の方法は、親である場合は分岐して終了することです。 os.fork()をご覧ください。

仕事をする関数は次のとおりです。

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)
25
edoloughlin

子プロセスは、同じプロセスグループにあるため、親プロセスと同じSIGINTを受け取ります。子プロセスでos.setpgrp()を呼び出すことにより、子を独自のプロセスグループに配置できます。 Popenのpreexec_fn引数はここで役立ちます:

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

(preexec_fnはun * x-oid専用です。Windowsの「creationflags = CREATE_NEW_PROCESS_GROUP」と大まかに同等のものがあるようですが、試したことはありません。)

48
JonMc