簡體   English   中英

從python運行一個程序,並在腳本被殺死后讓它繼續運行

[英]Run a program from python, and have it continue to run after the script is killed

我試過運行這樣的東西:

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。

子進程收到與父進程相同的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 ”似乎有一個粗略的等價物,但我從未嘗試過。)

在 Unix 系統上執行此操作的常用方法是如果您是父級,則 fork 並退出。 看看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)

經過一個小時的各種嘗試,這對我有用:

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

這是windows的解決方案。

從 3.2 開始,您還可以使用start_new_session標志(僅限 POSIX)。

import subprocess

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

請參閱Popen 構造函數中的 start_new_session

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 異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM