How to create a Linux daemon
Posted by jajcarmona on 2010/05/18
In Linux, a daemon is a program that runs in the background, rather than under the direct control of a user. It can be initiated by the user or by the system at boot time (in this case, it would be a system service).
The parent process of a daemon forks a child process that do the work and immediately after the forking, the parent exits. The child process keep running and the interface that launched the daemon (the parent process) doesn’t block.
An example of a Python daemon will be the next:
daemon.py file:
#!/usr/bin/env python
import sys, os, time, atexit
from signal import SIGTERMclass Daemon:
”"”
A generic daemon class.Usage: Subclass this class and override the ‘run’ method
”"”
def __init__(self, pidfile, stdin=’/dev/null’, stdout=’/dev/null’, stderr=’/dev/null’):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfiledef daemonize(self):
”"”
Do the ‘UNIX double-fork magic’
”"”
try:
pid = os.fork()
if pid > 0:
# Exit first parent
sys.exit(0)
except OSError, e:
sys.stderr.write(“Fork #1 failed: %d (%s)\n” % (e.errno, e.strerror))
sys.exit(1)# Decouple from parent environment
os.chdir(“/”)
os.setsid()
os.umask(0)# Do second fork
try:
pid = os.fork()
if pid > 0:
# Exit from second parent
sys.exit(0)
except OSError, e:
sys.stderr.write(“Fork #2 failed: %d (%s)\n” % (e.errno, e.strerror))
sys.exit(1)# Redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, ‘r’)
so = file(self.stdout, ‘a+’)
se = file(self.stderr, ‘a+’, 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())# Write pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
file(self.pidfile,’w+’).write(“%s\n” % pid)def delpid(self):
os.remove(self.pidfile)def start(self):
# Check for a pidfile to see if the daemon already runs
try:
pf = file(self.pidfile,’r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = Noneif pid:
message = “Pidfile %s already exist. Daemon already running?\n”
sys.stderr.write(message % self.pidfile)
sys.exit(1)# Start the daemon
self.daemonize()
self.run()def stop(self):
# Get the pid from the pidfile
try:
pf = file(self.pidfile,’r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = Noneif not pid:
message = “Pidfile %s does not exist. Daemon not running?\n”
sys.stderr.write(message % self.pidfile)
return # not an error in a restart# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find(“No such process”) > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)def restart(self):
self.stop()
self.start()def run(self):
”"”
You should override this method when you subclass Daemon. It will be called after the process has been
daemonized by start() or restart().
”"”
daemon-example.py file:
#!/usr/bin/env python
import sys, time
from daemon import Daemonclass MyDaemon(Daemon):
def run(self):
while True:
# Do any task here
time.sleep(1)if __name__ == “__main__”:
daemon = MyDaemon(‘/tmp/daemon-example.pid’)
if len(sys.argv) == 2:
if ‘start’ == sys.argv[1]:
daemon.start()
elif ‘stop’ == sys.argv[1]:
daemon.stop()
elif ‘restart’ == sys.argv[1]:
daemon.restart()
else:
print “Unknown command”
sys.exit(2)
sys.exit(0)
else:
print “Usage: %s start|stop|restart” % sys.argv[0]
sys.exit(2)
Note that in Daemon class, we check if a file named daemon-example.pid exists (the PID file), because if exists, it means that daemon is currently running and it’s not necessary to run it again. The file is created in a temporal files folder when we start the daemon and is deleted when we stop the daemon. If we want to run the daemon simultaneously in more than one user session, one solution could be the concatenation of the current user name to the PID file name (for example, daemon-example.currentusername.pid).
In a terminal, to start the daemon, we should run the next command:
python daemon-example.py start
to stop the daemon we should run the next command:
python daemon-example.py stop
and to restart the daemon we should run the next command:
python daemon-example.py restart
Try out to launch the daemon two times without stopping to see how the daemon doesn’t run again if is currently running.
Bibliography:
Article about Linux daemons: http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python
