Tuesday, June 30, 2009

Linux / *NIX minimal daemon code

Here is my minimal daemon code I wrote for Python 3. It is very minimal, but it works fine and can be easily extended.

Syntax highlighted version here.

#! /usr/bin/env python3

"""
Linux / *NIX daemon base code.

This script daemonizes its self with the start option and kills an already
running daemon with the stop option. It's kept minimal and simple, but it works
and can be extended/re-factored as base-code for a useful daemon.

Note: point of daemons is that they are quite and run in the background, add
some logging if you are developing a daemon, saves a lot of headaches.
"""

import os, sys, signal

PIDFILE = '/tmp/mydaemon.pid'

def daemonize(pidfile, workpath='/'):
pid = os.fork()
if pid > 0:
sys.exit(0)

os.chdir(workpath)
os.setsid()
os.umask(0)

pid = os.fork()
if pid > 0:
sys.exit(0)

sys.stdout.flush()
sys.stderr.flush()
si = open(os.devnull, 'r')
so = open(os.devnull, 'a+')
se = open(os.devnull, 'a+')
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())

pid = str(os.getpid())
with open(pidfile,'w+') as f:
f.write(pid + '\n')

def cleanup_handler(signum, frame):
os.remove(PIDFILE)

if __name__ == '__main__':
if sys.argv[1] == 'start':
if os.path.isfile(PIDFILE):
sys.stderr.write(
'pidfile found, daemon already running?\n')
sys.exit(2)

signal.signal(signal.SIGTERM, cleanup_handler)
daemonize(PIDFILE)
# daemon program logic
signal.pause()

elif sys.argv[1] == 'stop':
try:
with open(PIDFILE,'r') as pf:
pid = int(pf.read().strip())
except:
raise Exception('no pid found, daemon not running?')
os.kill(pid, signal.SIGTERM)

No comments:

Post a Comment