2013-11-03 100 views
0

我的计划是提供一个脚本,就像标题状态一样。我有一个想法,我会在下面讨论。如果您认为听起来不好/愚蠢,我会很感激任何有建设性的意见,改进等。python脚本启动2个守护进程

有2个服务我想作为守护进程启动。一个是必需的(一个缓存服务),一个是可选的(http访问缓存服务)。我使用​​模块获取--port获取缓存服务端口,并使用--http-port获得http访问权限。我已经有这个,它的工作。现在我想开始守护进程。服务基于扭曲,因此他们必须启动反应器循环。到目前为止,我想有两个不同的进程:一个用于服务,另一个用于http访问(尽管我知道它可能在单个异步进程中完成)。由于开始扭曲的服务是通过反应器循环完成的(这是python代码,而不是shell脚本,因为我还没有使用twistd),我认为使用os.fork比子进程(需要一个命令行命令启动该过程)。我可以使用os.fork来启动守护进程并触摸service.pidhttp.pid文件,但我不知道如何访问子进程的pid,因为os.fork为孩子返回0。

所以chld PID就是我所缺少的。此外,如果有什么不合逻辑或过于复杂的话,请对此发表评论。

我当前的代码如下所示:

./run.py 8001 # with main service only 

或:

./run.py 8001 --http-port 8002 # with additional http 

系统关机通过单一的shell脚本来完成:

#!/usr/bin/python 
import argparse 
import os 

from twisted.internet import reactor 

parser = argparse.ArgumentParser(description='Run PyCached server.') 
parser.add_argument('port', metavar='port', type=int, 
    help='PyCached service port') 
parser.add_argument('--http-port', metavar='http-port', type=int, default=None, 
    help='PyCached http access port') 
args = parser.parse_args() 

def dumpPid(name): 
    f = open(name + '.pid', 'w') 
    f.write(str(os.getpid())) 
    f.flush() 
    f.close() 

def erasePid(name): 
    os.remove(name + '.pid') 

def run(name, port, factory): 
    dumpPid(name) 
    print "Starting PyCached %s on port %d" % (name, port) 
    reactor.listenTCP(port, factory) 
    reactor.run() 
    erasePid(name) 
    print "Successfully stopped PyCached %s" % (name,) 

# start service (required) 
fork_pid = os.fork() 
if fork_pid == 0: 
    from server.service import PyCachedFactory 
    run('service', args.port, PyCachedFactory()) 
else: 
    # start http access (optional) 
    if args.http_port: 
     fork_pid = os.fork() 
     if fork_pid == 0: 
      from server.http import PyCachedSite 
      addr = ('localhost', args.port) 
      run('http', args.http_port, PyCachedSite(addr)) 
     else: 
      pass 

我运行它

#!/bin/bash 

function close { 
    f="$1.pid" 
    if [ -f "$f" ] 
    then 
     kill -s SIGTERM `cat "$f"` 
    fi  
} 

close http 
close service 

回答

2

由于启动扭曲服务是通过反应器循环完成的(这是python代码,而不是shell脚本,因为我还没有使用twistd),我认为使用os.fork比子进程要好命令行命令来启动进程)。

您应该使用twistd。如果没有,那么你应该写一个Python脚本来启动守护进程。然后,您应该使用subprocess模块(或reactor.spawnProcess)启动子进程。

使用os.fork而不立即进入os.exec*功能之一被破坏。由os.fork创建的父母和子女之间共享大量状态。你不能确定这个共享是不会破坏的东西(我可以告诉你会在中破坏Twisted中的一些东西)。

下面是一些讨论fork-without-exec问题的链接,这些链接可能会帮助您更深入地了解这是一个多么麻烦的领域。

+1

我喜欢你的答案,我可以从中学到一些东西。你能指点我一个网络/书籍资源,我可以读到关于'os.fork' /'os.exec *'/大量的状态吗?我对操作系统相似的东西很陌生,我不太明白你的意思。 PS似乎一切工作与上面的代码。这是否意味着它只是一个规模问题,直到某些事情中断? – ducin

+1

添加了一些您可能会感兴趣的链接。破坏很可能不是规模问题,而是您尝试使用的库代码的问题 - 在您开始调用某些与此用法交互不良的库功能之前,事情似乎可以正常工作(这可能会在您的应用程序保持不变,但*库*改变)。事实上,我不认为你发布的问题的代码可靠地工作:在Linux上它会使用epollreactor和epollreactor确实令人困惑,当与没有exec的fork一起使用时发生了破坏。 –