Python implementation of Linux daemon under the method of writing _python

Source: Internet
Author: User
Tags flush stdin

This article describes the Python implementation of Linux daemon process of writing methods, share for everyone to reference, I believe that the Python program for everyone will play a certain role in helping. The specific methods are as follows:

1. Call fork () so that the parent process can exit so that control is returned to the command line or shell program that runs your program. This step is required to ensure that the new process is not a process group leader process (processes group leader). Next, ' Setsid () ' will fail because you are the process group leader process. When a process calls the fork function, the operating system creates a new child process that is essentially identical to the parent process. A child process inherits copies of multiple values from the parent process, such as global variables and environment variables. The only difference between the two processes is the return value of the fork. The child (sub) process receives a return value of 0, and the parent process receives the PID of the subprocess as the return value. After calling the fork function, two processes execute the same program concurrently, first executing the next line of code after the fork is invoked. Both the parent process and the child process are executed concurrently and independently of each other, that is, they are "executed asynchronously".

2. Call ' Setsid () ' to become the leader process of a process group and session group . Since a control terminal is associated with a session and this new conversation has not yet acquired a control terminal, our process has no control over the terminal, which is a good thing for the daemon.

3. Call again ' fork () ' So the parent process (Session group leader Process) can exit . This means that we, a non conversation group leader process can never regain control of the terminal.

4. Call ' ChDir ('/') ' to confirm that our process does not maintain any directory in use state . Not doing this will cause the system administrator to uninstall (umount) a file system because it is our current working directory. [Similarly, we can change the current directory to the directory where the files are important for the daemon to run]

5. Call ' umask (0) ' so that we have full control over anything we write. We don't know what kind of umask we have inherited. [This step is optional] (Translator Note: This refers to step 5 because the daemon does not necessarily need to write a file)

6. Call ' Close () ' Closes the file descriptor 0,1 and 2. This frees up standard input, standard output, and standard error output inherited from the parent process. we have no way of knowing that these texts describe where character may have been redirected. Note that many daemons use ' sysconf () ' To confirm the ' _sc_open_max ' limit. ' _sc_open_max ' tells you the maximum number of files that each process can open. Then, using a loop, the daemon can close all possible file descriptors. You have to decide whether you need to do this or not. If you think there may be open file descriptors, you need to close them because the system has a limit on the number of files open at the same time.

7. Create a new file descriptor for standard input, standard output, and standard error output. even if you're not going to use them, it's a good idea to open them. The exact operation of these descriptors is based on their hobbies; For example, if you have a log file, you might want to open it as standard output and standard error output, and turn '/dev/null ' as the standard input; As an alternative, you can '/dev/' Console ' opens as standard error output and/or standard output, and '/dev/null ' as standard input, or any other binding method that is meaningful to your daemon. (Translator Note: Generally use the DUP2 function to atomically turn off and copy file descriptors.)

The implementation code is as follows:

# Core Modules Importatexit importos importsys importtime importsignal Classdaemon (object): "" A generic Daemo 
N class. 
         Usage:subclass the Daemon class and override the run () method "" Def __init__ (self, pidfile, Stdin=os.devnull, Stdout=os.devnull, Stderr=os.devnull, home_dir= '. ', umask=022, verbose=1): Self.stdin = stdin sel F.stdout = stdout Self.stderr = stderr Self.pidfile = pidfile Self.home_dir = Home_dir Self.verbose = Verbose Self.umask = Umask self.daemon_alive = True def daemonize (self): "" "Do the UNIX double-fork ma GIC, Stevens ' "Advanced programming in the UNIX environment" for details (ISBN 0201563177) "" Try:pid = Os.fork () If PID > 0: # Exit sys.exit (0) except OSError, E:SYS.STD Err.write ("Fork #1 failed:%d (%s) \ n"% (E.errno, e.strerror)) Sys.exit (1) # decouple from parent en 
   Vironment Os.chdir (Self.home_dir) Os.setsid () Os.umask (self.umask) # do second fork try:pid = Os.fork () If pid > 0: # Exit from second parent sys.exit (0) except OSError, E:SYS.STDERR.W  Rite ("Fork #2 failed:%d (%s) \ n"% (E.errno, e.strerror)) Sys.exit (1) If Sys.platform!= ' Darwin ': #  
      This blocks breaks on OS X # Redirect standard file descriptors Sys.stdout.flush () Sys.stderr.flush () Si = File (Self.stdin, ' r ') so = File (Self.stdout, ' A + ') if Self.stderr:se = File (self.stde RR, ' + ', 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 sigtermhandler (Signum, frame): Self.dae Mon_alive = False signal.signal (signal. Sigterm, Sigtermhandler) signal.signal (signal. SIGINT, Sigtermhandler) if Self.verbose ≫= 1:print "Started" # Write Pidfile atexit.register (self.delpid) # Make sure PID file is Remov Ed if we quit PID = str (os.getpid ()) file (Self.pidfile, ' w+ '). Write ("%s\n"% pid) def delpid (self): OS.R 
      Emove (Self.pidfile) def start (self, *args, **kwargs): "" "" Start the Daemon "" "If Self.verbose >= 1: Print "Starting ..." # Check for a pidfile to the if the daemon already runs TRY:PF = file (self.pidfi Le, ' r ') pid = Int (Pf.read (). Strip ()) Pf.close () except ioerror:pid = None except Systemex It:pid = None If Pid:message = "Pidfile%s already exists. 
    Is it already running?\n ' sys.stderr.write (message% self.pidfile) Sys.exit (1) # Start the daemon Self.daemonize () Self.run (*args, **kwargs) def stop (self): "" "" "Stop the Daemon" "" If Self.verbose = = 1:print "Stopping ..." # get the PID from the PIDFILe PID = self.get_pid () if not pid:message = ' Pidfile%s does not exist. Not running?\n ' sys.stderr.write (message% self.pidfile) # Just to be sure.  
        A ValueError might occur if the PID file is # Empty but does actually exist if Os.path.exists (self.pidfile): Os.remove (Self.pidfile) return # isn't an error in a restart # try killing the daemon process try : i = 0 while 1:os.kill (PID, signal. Sigterm) Time.sleep (0.1) i = i + 1 if i% = = 0:os.kill (PID, signal. Sighup) 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) if 
    Self.verbose >= 1:print "Stopped" def restart (self): "" "Restart the Daemon" "" Self.stop () 
  Self.start () def get_pid (self):  TRY:PF = File (self.pidfile, ' r ') pid = Int (Pf.read (). Strip ()) Pf.close () except IOError:  
    PID = none except Systemexit:pid = none return pid def is_running (self): PID = Self.get_pid ()  Print (PID) return PID and os.path.exists ('/proc/%d '% pid) def run (self): "" "You should override this 
When you subclass Daemon. 
It is called after the process has been daemonized by start () or restart ().

 """

Interested readers can debug and run the example code of this article, I believe there will be a new harvest.

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.