【问题标题】:subprocess gets killed even with nohup即使使用 nohup,子进程也会被杀死
【发布时间】:2016-05-09 14:57:30
【问题描述】:

我正在使用subprocess.Popen 启动多个进程。

代码是这样的:

while flag > 0:
   flag = check_flag()
   c = MyClass(num_process=10)
   c.launch()

MyClass 如果是以下内容:

MyClass(object)
   def __init__(self, num_process):
      self.num_process = num_process

   def launch(self):
      if self.check_something() < 10:
         for i in range(self.num_process):
             self.launch_subprocess()

   def launch_subprocess(self):
      subprocess.Popen(["nohup",
                       "python",
                       "/home/mypythonfile.py"],
                       stdout=open('/dev/null', 'w'),
                       stderr=open('logfile.log', 'w'),
                       shell=False)

在大多数情况下,启动的子进程会死掉,有时会在运行过程中死掉。在某些情况下,它会完成。

但是,如果我直接在 while 循环中使用subprocess.Popen,该过程会继续并及时完成。

有人可以告诉我,如何按照我上面描述的方式使用子进程来让进程在后台运行?

【问题讨论】:

  • (我不确定这是否重要),尽量保留对进程的引用以避免它们被垃圾收集,另外,您确定脚本不会正常终止吗?
  • 使用子进程调用另一个Python脚本有点奇怪。那个脚本在做什么,你不能直接导入和调用? multiprocessing 模块可以帮助您并行运行该脚本的代码。
  • 另一个脚本需要很长时间才能运行,这就是子进程的原因
  • @Pedru 是的。脚本不会正常终止。我正在跟踪它。此外,正如我所提到的,当直接使用子进程从 while 循环中调用相同的脚本时,可以正常工作!
  • 1- Popen() alone starts processes "in the background" 2- 什么意思“子进程被杀死” 你怎么知道? ps 输出?你在 bash 中按 Ctrl+C 吗?你退出 shell (Ctrl+D)。你看到任何错误吗?您是否尝试过生成唯一的日志文件名或使用附加模式:open('logfile.log', 'ab', 0)? 3- 不相关:使用close_fds=True

标签: python subprocess nohup


【解决方案1】:

nohup 仅在您的主进程正常退出时停止 SIGHUP 信号。对于 SIGINT 或 SIGTERM 等其他信号,子进程会收到与父进程相同的信号,因为它位于同一进程组中。有两种方法使用 Popen 的 preexec_fn 参数。

设置子进程组:

subprocess.Popen(['nohup', 'python', '/home/mypythonfile.py'],
                 stdout=open('/dev/null', 'w'),
                 stderr=open('logfile.log', 'a'),
                 preexec_fn=os.setpgrp )

更多信息请参见另一个post

让子进程忽略这些信号:

def preexec_function():
    signal.signal(signal.SIGINT, signal.SIG_IGN)
subprocess.Popen( ... , preexec_fn=preexec_function)

【讨论】:

  • 实际上我无法在我的 CentOS7 机器上用 Python2.7 重现你的问题。您的问题似乎是特定于平台的。如果上述解决方案不起作用,请提供更多子进程的调试信息(使用gdb 查看导致其流产的信号)。
  • 我在 ubuntu 14.04 上。我会检查 gdb
  • 最后,我能够在 Raspbian RPi 的后台启动 ngrok,并且在 python 脚本完成时不会将其杀死。谢谢。
猜你喜欢
  • 2010-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 2015-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多