Original reference: http://blog.csdn.net/tao_627/article/details/49532021
A daemon is a process that has a long lifetime. They are independent of the control terminal and periodically perform certain tasks or wait to handle certain occurrences. They often start when the system boots and terminate when the system shuts down.
Features of the daemon process
1. Running in the background
2. Isolate itself from the environment before it runs. These environments include file descriptors that are not closed, control terminals, session and process groups, working directories, and file creation masks. These environments are typically inherited by daemons from the parent process that executes it, especially the shell.
3. Starting mode is special, it can be started from startup script/etc/rc.d at system startup, can be started by inetd Daemon, can be started by Crond, and can be executed by user terminal (usually shell).
In short, despite these peculiarities, daemons are basically no different from ordinary processes. Therefore, the process of writing a daemon is actually transforming a normal process into a daemon based on the nature of the daemon described above.
Daemon Programming Rules
1. Run in the background, call Fork, and then exit the parent process
2. Out of control terminal, login session and process group, call Setsid () to make the process a session leader
3. Disable process re-opening control terminal
4. Close Open file descriptor, call fclose ()
5. Change the current working directory to the root directory.
6. Reset the file creation mask to 0
7. Handling SIGCHLD Signals
Here is an example of demo source code:
#!/usr/bin/Env Python#encoding:utf-8#description: A simple wrapper class for a daemon, with the usual start|stop|restart|status function, ease of use # The program that needs to be transformed into a daemon only needs to rewrite the base class's run function to #date: --Ten- in#usage: Start: Python daemon_class.py start# off: Python daemon_class.py stop# Status: Python daemon_class.py stat us# restart: Python daemon_class.py restart# view: PS-AXJ |grep daemon_classimport atexit, OS, sys, TIME, signalclassCdaemon:" "A generic daemonclass. Usage:subclass the CdaemonclassandOverrideThe Run () method stderr represents the error log file absolute path, collects the error log during startup process verbose indicates that the exception error message will be started during the run process to print to the terminal, easy to debug, recommended non-debug mode off, the default is 1, which means to open Save_path indicates the absolute path of the daemon PID file" "def __init__ (self, Save_path, Stdin=os.devnull, Stdout=os.devnull, Stderr=os.devnull, home_dir='.', umask=022, verbose=1): Self.stdin=stdin self.stdout=stdout Self.stderr=stderr self.pidfile=Save_path #pid文件绝对路径 Self.home_dir=Home_dir Self.verbose=verbose #调试开关 self.umask=umask self.daemon_alive=True def daemonize (self):Try: PID=os.fork ()ifPID >0: Sys.exit (0) except OSError, E:sys.stderr.write ('Fork #1 failed:%d (%s) \ n'%(E.errno, E.strerror)) Sys.exit (1) Os.chdir (Self.home_dir) Os.setsid () os.umask (self.umask)Try: PID=os.fork ()ifPID >0: Sys.exit (0) except OSError, E:sys.stderr.write ('Fork #2 failed:%d (%s) \ n'%(E.errno, E.strerror)) Sys.exit (1) Sys.stdout.flush () Sys.stderr.flush () Si= File (Self.stdin,'R') So= File (Self.stdout,'A +') ifSelf.stderr:se= File (Self.stderr,'A +',0) Else: Se=So os.dup2 (Si.fileno (), Sys.stdin.fileno ()) os.dup2 (So.fileno (), Sys.stdout.fileno ()) os.dup2 (SE . Fileno (), Sys.stderr.fileno ()) def sig_handler (Signum, frame): Self.daemon_alive=False signal.signal (signal. SIGTERM, Sig_handler) signal.signal (signal. SIGINT, Sig_handler)ifSelf.verbose >=1: Print'daemon process started ...'Atexit.register (self.del_pid) PID=Str (os.getpid ()) file (Self.pidfile,'w+'). Write ('%s\n'%pid) def get_pid (self):Try: PF= File (Self.pidfile,'R') PID=int(Pf.read (). Strip ()) Pf.close () except Ioerror:pid=None except Systemexit:pid=Nonereturnpid def del_pid (self):ifos.path.exists (self.pidfile): Os.remove (Self.pidfile) def start (self,*args, * *Kwargs):ifSelf.verbose >=1: Print'Ready to starting ...'#check forA PID file to seeifThe daemon already runs PID=self.get_pid ()ifpid:msg='pid file%s already exists, is it already running?\n'Sys.stderr.write (msg%self.pidfile) Sys.exit (1) #start the daemon Self.daemonize () Self.run (*args, * *Kwargs) def stop (self):ifSelf.verbose >=1: Print'stopping ...'PID=self.get_pid ()ifNot pid:msg='pid file [%s] does not exist. Not running?\n'%self.pidfile sys.stderr.write (msg)ifos.path.exists (self.pidfile): Os.remove (self.pidfile)return #TryTo kill the daemon processTry: I=0 while 1: Os.kill (PID, signal. SIGTERM) Time.sleep (0.1) I= i +1 ifITen==0: Os.kill (PID, signal. SIGHUP) except OSError, Err:err=Str (ERR)ifErr.find ('No Such process') >0: ifos.path.exists (self.pidfile): Os.remove (self.pidfile)Else: Print str (ERR) sys.exit (1) ifSelf.verbose >=1: Print'stopped!'def restart (self,*args, * *Kwargs): Self.stop () Self.start (*args, * *Kwargs) def is_running (self): PID=self.get_pid () #print (PID)returnPID and Os.path.exists ('/proc/%d'%PID) def run (self,*args, * *Kwargs):'Note:override the method in subclass'Print'base class run ()'classClientdaemon (Cdaemon): Def __init__ (self, name, Save_path, stdin=os.devnull, Stdout=os.devnull, Stderr=os.devnull, home_dir='.', umask=022, verbose=1): cdaemon.__init__ (Self, save_path, stdin, stdout, stderr, Home_dir, umask, verbose) self.name=name #派生守护进程类的名称 def run (self, OUTPUT_FN,**Kwargs): FD= Open (OUTPUT_FN,'W') whileTrue:line= Time.ctime () +'\ n'Fd.write (line) Fd.flush () Time.sleep (1) Fd.close ()if__name__ = ='__main__': Help_msg='Usage:python%s <start|stop|restart|status>'% sys.argv[0] ifLen (sys.argv)! =2: Print help_msg sys.exit (1) P_name='Clientd'#守护进程名称 PID_FN='/tmp/daemon_class.pid'#守护进程pid文件的绝对路径 LOG_FN='/tmp/daemon_class.log'#守护进程日志文件的绝对路径 ERR_FN='/tmp/daemon_class.err.log'#守护进程启动过程中的错误日志, internal error can see the CD from here= Clientdaemon (P_name, PID_FN, STDERR=ERR_FN, verbose=1) ifsys.argv[1] =='Start': Cd.start (LOG_FN) elif sys.argv[1] =='Stop': Cd.stop () elif sys.argv[1] =='Restart': Cd.restart (LOG_FN) elif sys.argv[1] =='Status': Alive=cd.is_running ()ifAlive:print'Process [%s] is running ...'%cd.get_pid ()Else: Print'daemon Process [%s] stopped'%Cd.nameElse: Print'Invalid argument!'Print Help_msg
Here is the run
The resulting log file is
Reference Document Http://zhidao.baidu.com/link?url= 3ogf3-g9x9tlr-vryag-hc8hiyxxkqzncxbe1c7m4rxzbbbookohkyi-vv9mcz5dvljekexegbolo-5mcsyupxp3uv4--7-5gndblsqqd0s Very good reference value http://blog.csdn.net/mr_jj_lian/article/details/7252222 principle explained very in place http://www.jb51.net/article/54199.htm are good, This daemon class package is very complete, I have re-organized the reference: Python implementation daemon
How to implement the daemon daemon in Python