我尝试过这样的事情:
subprocess.Popen(['nohup', 'my_command'],
stdout=open('/dev/null', 'w'),
stderr=open('logfile.log', 'a'))
如果父脚本正常退出,则此方法有效,但如果我终止脚本(Ctrl-C),则所有子进程也将被终止。有没有办法避免这种情况?
我关心的平台是OS X和Linux,使用Python 2.6 和 Python 2.7。
答案 0 :(得分:46)
子进程接收与父进程相同的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-oids。似乎有一个粗略的等效Windows“creationflags = CREATE_NEW_PROCESS_GROUP”,但我从未尝试过。)
答案 1 :(得分:25)
在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)
答案 2 :(得分:2)
经过一个小时的尝试,这对我有用:
process = subprocess.Popen(["someprocess"], creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP)
这是Windows的解决方案。
答案 3 :(得分:0)
with open('/dev/null', 'w') as stdout, open('logfile.log', 'a') as stderr:
subprocess.Popen(['my', 'command'], stdout=stdout, stderr=stderr)
类子流程。Popen(...)
在新进程中执行子程序。 在POSIX上,该类使用类似于os.execvp()的行为来执行 子程序。在Windows上,该类使用Windows CreateProcess() 功能。
os.execvpe(file,args,env)
这些功能全部执行一个新程序,替换当前程序 处理;他们不回来。在Unix上,新的可执行文件已加载 进入当前进程,并具有与 呼叫者。错误将被报告为OSError异常。
答案 4 :(得分:0)
从3.2开始,您还可以使用start_new_session
标志(仅适用于POSIX)。
import subprocess
p = subprocess.Popen(["sleep", "60"], start_new_session=True)
ret = p.wait()