我在远程计算机上运行守护程序: mydaemon 。该守护进程应始终持续运行。
当我在远程计算机上运行作业时,它还会启动一个轻量级的python服务器进程 my_remote_server.py 。
我可以发送到 my_remote_server.py 的其中一个命令是重启 mydaemon ,我正试图这样做:
os.system("killall mydaemon")
subprocess.Popen(["mydaemon"], stdin=None, stdout=None, stderr=None, close_fds=True)
当我的工作结束时, my_remote_server.py 应该终止,但 mydaemon 应该继续运行。但是我看到 my_remote_server.py 卡在僵尸进程中(这导致系统看不到我的作业被终止)
820 root Z [my_remote_serve]
834 root 552 S /usr/sbin/telnetd -l /bin/sh
835 root 836 S /bin/sh
844 root 672 S mydaemon
我想从孩子( mydaemon )中分离父母( my_remote_server.py ),但我无法弄清楚如何。
- 我的python版本是2.5.4
我认为我现在更了解守护进程,但是我仍然无法让守护进程分离
我为了简洁而省略了错误处理
os.system("killall mydaemon")
if(os.fork() > 0):
return True # my_remote_server.py returns to handle additional commands
os.setsid()
if(os.fork() > 0):
exit(0) # first child exits after becoming session leader
os.execlp("mydaemon") # have the second child run as the daemon
在我调用restart_mydaemon函数
之前,这是我的ps列表252 root 672 S mydaemon
286 root 4552 S /usr/bin/python my_remote_server.py
这是在restart_mydaemon之后,第一个孩子被僵尸(不应该消失吗?)
286 root 4552 S /usr/bin/python my_remote_server.py
300 root Z [my_remote_serve]
304 root 672 S [mydaemon]
这是作业终止的时候(my_remote_server.py应该已经退出,但是它是一个僵尸,但是,现在第一个孩子已经退出了)
286 root Z [my_remote_serve]
304 root 1012 S [mydaemon]
答案 0 :(得分:1)
将进程转换为守护进程是一个多步骤的过程。您的部分问题是您的父进程没有正确等待子终止(请参阅wait / waitpid),
你必须再次分叉,以完全脱离(大)父母
try:
#free parent, detach from process group
pid = os.fork()
if( pid>0 ):
exit(0) #parent exits
except OSError, e:
raise Exception("%s [%d]" % (e.strerror, e.errno))
#become session leader, process group leader, detach from controlling terminal
os.setsid()
try:
#prevent zombie process, make init cleanup
pid = os.fork()
if( pid>0 ):
exit(0) #parent exits
except OSError, e:
raise Exception("%s [%d]" % (e.strerror, e.errno))
#change directories, close stdin/out/err, etc
os.chdir(MYDIR)
os.umask(MYMASK)
#close files (including stdin, stdout, stderr)
#(re)open new stdin/stdout, if desired
答案 1 :(得分:0)
请查看此处以获取有关守护程序如何工作的参考/良好解释:
http://code.activestate.com/recipes/278731/
总的来说这非常重要,我会尝试使用python-daemon库或类似的库:
答案 2 :(得分:0)
我不会调用子进程来执行此操作。子进程imo仅应用于运行无法导入的命令。
因此,在这种情况下,您的my_remote_server.py可以导入mydaemon并运行它。
您有2种方法可以做到这一点。您可以将my_remote_server设置为父级,将mydaemon设置为子级。或有一个新的脚本作为父脚本并生成2个子脚本(mydaemon,my_remote_server)。
例如。在下面,我创建一个子进程。全局范围,因为我需要在龙卷风的HTTP处理程序中访问它。我设置了Web服务器。启动子进程,然后启动Web服务器。命中端点后,处理程序将运行,并将子进程从全局范围中拉出。我们终止子进程并打印。您可以向龙卷风添加更多终结点,以再次启动子级,或者停止然后重新启动它。
remote.py:
import multiprocessing
import deamon
import tornado.ioloop
import tornado.web
child_pro = multiprocessing.Process(target=deamon.run_deamon)
child_pro.daemon = True
class MainHandler(tornado.web.RequestHandler):
def get(self):
global child_pro
child_pro = child_pro # type: multiprocessing.Process
child_pro.terminate()
print ("Child killed")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
global child_pro
app = make_app()
app.listen(8888)
child_pro.start()
tornado.ioloop.IOLoop.current().start()
deamon.py:
import time
def run_deamon():
while True:
time.sleep(2)
print ('child alive')