【问题标题】:python script starting 2 daemonspython脚本启动2个守护进程
【发布时间】: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.pidhttp.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

【问题讨论】:

    标签: python twisted daemon


    【解决方案1】:

    由于启动 twisted 服务是通过 reactor 循环完成的(这是 python 代码,而不是 shell 脚本,因为我还没有使用 twistd),我认为使用 os.fork 比 subprocess 更好(这需要一个命令行命令来启动进程)。

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

    使用os.fork 而不立即执行os.exec* 函数之一已损坏。 os.fork 创建的父子节点之间共享大量状态。你不能确定这个分享不会破坏某些东西(我可以告诉你它破坏 Twisted 中的一些东西)。

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

    【讨论】:

    • 我喜欢你的回答,我可以从中学到一些东西。你能否指点我一个网络/书籍资源,在那里我可以阅读os.fork/os.exec*/大量的状态?我对类似操作系统的东西很陌生,我不太明白你在这里的意思。 PS一切似乎都可以使用上面的代码。这是否意味着在出现问题之前只是规模问题?
    • 添加了一些您可能会感兴趣的链接。损坏很可能不是规模问题,而是您尝试使用哪个库代码的问题 - 在您开始调用一些与此用法交互不佳的库功能之前,事情似乎工作得很好(这可能发生在您的应用程序保持不变,但 library 更改)。实际上,我认为您在问题中发布的代码并不可靠:在 linux 上它将使用 epollreactor 并且 epollreactor 在与 fork 没有 exec 的情况下使用时确实令人困惑,损坏。
    猜你喜欢
    • 2012-08-05
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多