【发布时间】:2013-11-03 12:22:05
【问题描述】:
我的计划是提供一个脚本,正如标题所述。我有一个想法,我将在下面描述。如果您认为某些事情听起来很糟糕/愚蠢,我将不胜感激任何建设性的 cmets、改进等。
有 2 个服务我想作为守护进程启动。一个是必需的(缓存服务),一个是可选的(http 访问缓存服务)。我使用argparse 模块来获取--port 来获取缓存服务端口和可选的--http-port 来获取http 访问。我已经有了这个并且它有效。现在我想启动守护进程。这些服务是基于twisted的,所以它们必须启动reactor循环。到目前为止,我希望有两个不同的进程:一个用于服务,第二个用于 http 访问(尽管我知道它可能在单个异步进程中完成)。
由于启动扭曲服务是通过反应器循环完成的(这是 python 代码,而不是 shell 脚本,因为我还没有使用 twistd),我认为使用 os.fork 比 subprocess 更好(需要用于启动进程的命令行命令)。我可以使用os.fork 启动守护进程并触摸service.pid 和http.pid 文件,但我不知道如何访问子pid,因为os.fork 为子返回0。
所以 chld PID 是我所缺少的。此外,如果任何事情看起来不合逻辑或过于复杂,请对此发表评论。
我当前的代码如下所示:
#!/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
我运行它:
./run.py 8001 # with main service only
或:
./run.py 8001 --http-port 8002 # with additional http
系统关闭是通过单个 shell 脚本完成的:
#!/bin/bash
function close {
f="$1.pid"
if [ -f "$f" ]
then
kill -s SIGTERM `cat "$f"`
fi
}
close http
close service
【问题讨论】: