45

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

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

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

私が気にかけているプラ​​ットフォームは、Python2.6Python2.7を使用するOSXとLinuxです。

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_fnun * x-oids専用です。Windows" creationflags=CREATE_NEW_PROCESS_GROUP"にほぼ相当するものがあるようですが、試したことはありません。)

于 2013-06-04T22:26:57.047 に答える
31

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)
于 2011-05-15T21:14:44.823 に答える
6

さまざまな試みを1時間行った後、これは私にとってはうまくいきます。

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

それは窓のための解決策です。

于 2020-08-01T18:01:57.473 に答える
1

start_new_session3.2以降では、フラグも使用できます(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(file、args、env)

これらの関数はすべて新しいプログラムを実行し、現在のプロセスを置き換えます。彼らは戻りません。Unixでは、新しい実行可能ファイルが現在のプロセスにロードされ、呼び出し元と同じプロセスIDを持ちます。エラーはOSError例外として報告されます。

于 2020-03-03T19:51:33.910 に答える