从 python 运行一个程序,并在脚本被终止后让它继续运行
我尝试过运行这样的事情:
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。
I've tried running things like this:
subprocess.Popen(['nohup', 'my_command'],
stdout=open('/dev/null', 'w'),
stderr=open('logfile.log', 'a'))
This works if the parent script exits gracefully, but if I kill the script (Ctrl-C), all my child processes are killed too. Is there a way to avoid this?
The platforms I care about are OS X and Linux, using Python 2.6 and Python 2.7.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
子进程收到与父进程相同的
SIGINT
,因为它位于同一进程组中。您可以通过在子进程中调用 os.setpgrp() 来将子进程放入其自己的进程组中。Popen
的preexec_fn
参数在这里很有用:(preexec_fn
仅适用于 un*x-oids。对于 Windows 似乎有一个粗略的等效项“creationflags=CREATE_NEW_PROCESS_GROUP
”,但我从未尝试过。)The child process receives the same
SIGINT
as your parent process because it's in the same process group. You can put the child in its own process group by callingos.setpgrp()
in the child process.Popen
'spreexec_fn
argument is useful here:(
preexec_fn
is for un*x-oids only. There appears to be a rough equivalent for Windows "creationflags=CREATE_NEW_PROCESS_GROUP
", but I've never tried it.)在 Unix 系统上执行此操作的常用方法是 fork 并退出(如果您是父级)。看看 os.fork() 。
这是一个完成这项工作的函数:
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:
经过一小时的各种尝试后,这对我有用:
这是 Windows 的解决方案。
After an hour of various attempts, this works for me:
It's solution for windows.
从 3.2 开始,您还可以使用
start_new_session
标志(仅限 POSIX)。请参阅 Popen 构造函数中的 start_new_session
Since 3.2 you can also use
start_new_session
flag (POSIX only).See start_new_session in Popen constructor
另一种方法是让子进程忽略 SIGINT。
使用 preexec_fn 可确保父进程的 SIGINT 处理程序不会更改。 (如果更改了,您需要像这样恢复它。)
当然,这只有在子进程不继续时才有效恢复信号处理程序。在以下子进程安装信号处理程序的情况下,子进程仍然会被终止:
归功于 https://stackoverflow.com/a /3731948/5267751 。
Another way is to make the subprocess ignore SIGINT.
Using
preexec_fn
ensures that the parent process's SIGINT handler is not changed. (if it's changed you need to restore it like this.)Of course, this will only work if the subprocess does not proceed to reinstate the signal handler. In the following case where the subprocess installs a signal handler, the subprocess would still be killed:
Credit to https://stackoverflow.com/a/3731948/5267751 .