Я планирую предоставить сценарий, как указано в заголовке. У меня есть идея, о которой я расскажу ниже. Если вы считаете, что что-то звучит плохо / глупо, буду благодарен за любые конструктивные комментарии, улучшения и т. Д.
Есть 2 службы, которые я хочу запустить как демоны. Один обязателен (служба кеширования), другой - необязательный (HTTP-доступ к службе кеширования). Я использую модуль argparse
, чтобы получить --port
, чтобы получить порт службы кеширования, и необязательный --http-port
, чтобы получить доступ по протоколу http. Это у меня уже есть, и это работает. Теперь я хочу запустить демонов. Эти сервисы основаны на кручении, поэтому они должны запускать петлю реактора. Пока я хотел бы иметь два разных процесса: один для службы, а второй для доступа по http (хотя я знаю, что это может быть выполнено в одном асинхронном процессе).
Поскольку запуск скрученной службы выполняется через цикл реактора (который представляет собой код Python, а не сценарий оболочки, поскольку я еще не использую twistd
), я думаю, что использование os.fork
лучше, чем подпроцесс (для которого потребуется команда командной строки для запуска процесс). Я могу использовать 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
or:
./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