Pregunta

I have a python script which I want to run as a daemon under daemontools. Usually the service running under deamontools runs in foreground and if it goes down, daemontools will restart it. The service should also handle signals as described here.

My program catches SIGINT and SIGALRM and when the signals are received program exits.

When the program is run from command line and kill -1 <pid> and kill -15 <pid> is signaled, the signal handler is run, which causes program to exit, and corresponding logs are printed.

But when the program is run under daemontools, and svc -d /service/myrogram is executed, the program neither exits nor logs are printed.

I am using following run script to run the program under daemontools

#!/bin/sh
exec 2>&1
/usr/bin/python /home/test/sigtest.py

I am wondering why kill -15 <pid> works while svc -d /service/myrogram does not seems to deliver the signal to the python program.

The python script I am working with is:

from pyudev import Context, Monitor, MonitorObserver
import signal, sys, time

def print_device_event(device):
    print ('New event - {0.action}: {0.device_path}'.format(device))

if __name__ == '__main__':
    context = Context()
    monitor = Monitor.from_netlink(context)
    observer = MonitorObserver(monitor, callback=print_device_event, name='monitor-observer')
    print ("Processing started")
    observer.start()
    def handler(signum, frame):
        print("Received Signal: %d"%signum)
        observer.send_stop()
        print("Exiting.")
    signal.signal(signal.SIGTERM, handler)
    signal.signal(signal.SIGHUP, handler)

    try:
        while observer.is_alive():
            observer.join(timeout=1.0)
    except (KeyboardInterrupt, SystemExit):
        print("Caught KeyboardInterrupt, exiting")
        observer.send_stop()
¿Fue útil?

Solución

I am using following run script to run the program under daemontools

#!/bin/sh
exec 2>&1
/usr/bin/python /home/test/sigtest.py

And there's your error. You're forking a child process to run the python program in. Stop your daemon from forking. Daemons do not need to, and should not, fork to run in a child process, be they running under daemontools, daemontools-encore, runit, s6, perp, or even systemd.

The standard operation of the shell, remember, is to fork and run commands in child processes.

For best results, you should acclimate yourself to writing run scripts using something other than the shell, that chain loads daemon programs. Here's your run script using Laurent Bercot's execline instead of /bin/sh as the script interpreter:

#!/command/execlineb -PW
fdmove -c 2 1
/usr/bin/python /home/test/sigtest.py

execline doesn't have any of the overhead of all of the things that even non-interactive shells do, including parsing startup "rc" files. And it comes with a useful suite of chain loading utilities for doing many of the things that one might want to do in run scripts.

But even execline does things that you don't need in a run script. Hence the -P option to turn off argument pushing, which has no utility for run scripts. Here's your run script using an even more barebones script interpreter, my nosh program:

#!/usr/local/bin/nosh
fdmove -c 2 1
/usr/bin/python /home/test/sigtest.py

Finally, here's your run script for /bin/sh, corrected:

#!/bin/sh
exec 2>&1
exec /usr/bin/python /home/test/sigtest.py

Further reading

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top