Я хочу создать демон Manager
, который порождает два подпроцесса A
и B
. Когда демон Manager
умирает / убивается, он должен убить A
и B
. В настоящее время он настроен так, что если я передам "stop"
в Manager
, он отправит SIGTERM
в свою группу процессов, которая убивает все.
Однако мне бы хотелось, чтобы, если я отправлю SIGTERM
на Manager
напрямую, это также убило бы A
и B
. Я пробовал обработчики сигналов, но это создает цикл, в котором он отправляет SIGTERM
на PG, который отправляет его обратно на Manager
и т. Д.
Я также пытался сделать Manager
лидером группы процессов, вызвав os.setpgid(os.getpid(), os.getpid())
до появления A
и B
, но это, похоже, не убивает A
и B
должным образом.
В приведенном ниже примере выполнение python manager.py start
приведет к созданию Manager
, A
и B
. Тогда:
python manager.py stop
уничтожит все 3 процесса
kill -INT -$MANAGER_PGID
убьет всех 3
kill $MANAGER_PID
убьет только Manager
, а не A
или B
#!/usr/bin/env python2.7
import atexit
import datetime
import os
import sys
import time
import subprocess
from signal import *
class Daemon(object):
def __init__(self):
self.pid_file = "/var/run/manager.pid"
def del_pid(self):
os.remove(self.pid_file)
def daemonize(self):
if os.fork():
sys.exit()
os.chdir("/")
os.setsid()
os.umask(0)
if os.fork():
sys.exit()
with open('/dev/null', 'r') as dev_null:
os.dup2(dev_null.fileno(), sys.stdin.fileno())
sys.stderr.flush()
err = "/tmp/manager.err"
with open(err, 'a+', 0) as stderr:
os.dup2(stderr.fileno(), sys.stderr.fileno())
sys.stdout.flush()
out = "/tmp/manager.out"
with open(out, 'a+', 0) as stdout:
os.dup2(stdout.fileno(), sys.stdout.fileno())
atexit.register(self.del_pid)
pid = os.getpid()
with open(self.pid_file, 'w+') as pid_file:
pid_file.write('{0}'.format(pid))
os.setpgid(pid, pid)
# for sig in (SIGABRT, SIGTERM, SIGINT):
# signal(sig, self.stop)
def get_pid_by_file(self):
with open(self.pid_file, 'r') as pid_file:
pid = int(pid_file.read().strip())
return pid
def start(self):
self.daemonize()
self.run()
def stop(self, signum=None, frame=None):
pid = self.get_pid_by_file()
pgid = os.getpgid(pid)
os.killpg(pgid, SIGTERM)
def run(self):
subprocess.Popen("a.sh", shell=True)
subprocess.Popen("a.sh", shell=True)
while 1:
time.sleep(5)
if __name__ == '__main__':
daemon = Daemon()
if 'start' == sys.argv[1]:
daemon.start()
elif 'stop' == sys.argv[1]:
daemon.stop()