How to implement the daemon daemon in Python

Source: Internet
Author: User
Tags stdin

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

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.