2013-11-03 137 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一起使用時發生了破壞。 –