0

私の計画は、タイトルが示すとおりのスクリプトを提供することです。以下に説明するアイデアがあります。何かが悪い/ばかげていると思われる場合は、建設的なコメント、改善などに感謝します.

デーモンとして開始したいサービスが 2 つあります。1 つは必須 (キャッシュ サービス)、もう 1 つはオプション (キャッシュ サービスへの http アクセス) です。argparseモジュールを使用--portしてキャッシュ サービス ポートを取得し、オプション--http-portで http アクセスを取得します。私はすでにこれを持っていて、うまくいきます。次に、デーモンを開始します。サービスはツイストに基づいているため、リアクター ループを開始する必要があります。これまでのところ、2 つの異なるプロセスが必要です。1 つはサービス用で、もう 1 つは http アクセス用です (ただし、単一の非同期プロセスで実行できることはわかっています)。

ツイスト サービスの開始はリアクター ループ (まだ使用していないため、シェル スクリプトではなく Python コード) を介して行われるため、サブプロセス (プロセスを開始するにはコマンド ライン コマンドが必要) よりもtwistd使用の方が優れていると思います。os.fork. os.forkデーモンとタッチservice.pidとファイルを起動するために使用できますhttp.pidが、os.fork が子に対して 0 を返すため、子 pid にアクセスする方法がわかりません。

したがって、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

システムのシャットダウンは、単一のシェル スクリプトを介して実行されます。

#!/bin/bash

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

close http
close service
4

1 に答える 1

2

ツイスト サービスの開始はリアクター ループ (twistd をまだ使用していないため、シェル スクリプトではなく Python コード) を介して行われるため、os.fork を使用する方がサブプロセスよりも優れていると思います (サブプロセスにはコマンド ライン コマンドが必要です)。プロセスを開始します)。

twistd を使うべきです。そうでない場合は、デーモンを起動するための Python スクリプトを作成する必要があります。次に、subprocessモジュール (またはreactor.spawnProcess) を使用して子プロセスを起動する必要があります。

os.fork機能の 1 つにすぐに進まないで使用os.exec*すると壊れます。によって作成された親と子の間で大量の状態が共有されos.forkます。この共有が何かを壊さないとは断言できません (そして、Twisted で何かが壊れると断言できます)。

これがどのような厄介な領域であるかを理解するのに役立つかもしれない fork-without-exec の問題に関する議論へのリンクがいくつかあります。

于 2013-11-03T17:15:45.037 に答える