我有一个python程序,它使用subprocess.Popen
来启动另一个进程(python进程或其他),并在启动它之后,将子进程的PID保存到文件中。让我们假设父进程突然死亡(因为异常或其他)。有没有办法再次访问Popen
返回的对象?
我的意思是,基本的想法是首先读取文件,如果它存在并且上面写有PID,那么访问该过程,以便知道返回代码或其他什么。如果没有PID,则使用Popen
启动该过程。
非常感谢!!
答案 0 :(得分:2)
Popen对象实际上只是子进程PID,stdin,stdout和stderr的包装器,还有一些使用它们的便利函数。
所以问题是为什么你需要访问Popen对象?您想与孩子沟通,终止它,还是检查它是否仍在运行?
在任何情况下都无法为已经运行的进程重新获取Popen对象。
接近这个问题的正确方法是将孩子作为守护进程启动,就像东武建议的那样。守护进程的部分过程是关闭stdin和stdout,因此您无法使用它们与子进程进行通信。相反,大多数守护进程使用管道或套接字来允许客户端连接到它们并向它们发送消息。
与孩子交谈的最简单方法是从子进程打开命名管道,例如: / etc / my_pipe,从父/控制进程打开该命名管道,并从中写入/读取。
在快速浏览一下python-daemon之后,在我看来,python-daemon会帮助你对你的子进程进行守护,这很难做到,但它对你的消息传递方面没有帮助。
但就像我说的那样,我认为你需要告诉我们为什么你需要一个Popen对象用于子进程才能进一步帮助你。
答案 1 :(得分:1)
如果进程终止,则关闭其所有打开的文件句柄。这包括popen()
创建的所有未命名管道。所以,不,没有办法从PID中恢复Popen
对象。操作系统甚至不会将您的新流程视为父流程,因此您甚至不会收到SIGCHLD
个信号(尽管waitpid()
可能仍然有效)。
我不确定孩子是否也能保证存活,因为写入没有读者的管道(即孩子的重定向stdout
)应该用{{1}来杀死孩子}}
如果您希望父进程选择孩子离开的位置,则需要生成子进程以写入文件,通常是SIGPIPE
或/tmp
,并让其记录其PID就像你现在一样(通常的位置是/var/log
)。 (将其写入命名管道可能会导致使用/var/run
将其杀死,如上所述。)如果使用PID后缀文件名,则管理器进程很容易找出哪个文件属于哪个守护程序。 / p>
答案 2 :(得分:0)
看起来你正在尝试编写一个守护进程,它需要pidfile支持。你不能错过python-daemon。
例如:
import daemon
import lockfile
import os
with daemon.DaemonContext(pidfile=lockfile.FileLock('/var/run/spam.pid')):
os.execl('/path/to/prog', args…)