Python implementation of Linux under the daemon process of writing methods

Source: Internet
Author: User
This article describes the Python implementation of Linux under the protection process of writing methods, share for everyone to reference, I believe that the Python program design for everyone will play a role in helping. Here's how:

1. Call fork () so that the parent process can exit so that the 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 (process leader). Next, ' Setsid () ' will fail because you are the process group leader process. When the process calls the fork function, the operating system creates a new child process that is essentially the same as 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 process receives a return value of 0, and the parent process receives the PID of the child process 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 called. Parent and child processes are executed concurrently and independently of each other, that is, they are "executed asynchronously."

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

3. Call ' fork () ' again so the parent process (conversation 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 not 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 daemons are important to run]

5. Call ' umask (0) ' so that we have full control of 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 files)

6. Call ' Close () ' to close the file descriptor 0,1 and 2. This frees up the 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. Notice that many daemons use ' sysconf () ' To confirm the ' _sc_open_max ' restrictions. ' _sc_open_max ' tells you the maximum number of files 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 it is possible to have open file descriptors, you need to close them because the system has a limit of the number of open files at the same time.

7. Create a new file descriptor for standard input, standard output, and standard error output. Even if you don't plan 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 open '/dev/null ' as standard input; As an alternative, you can put '/dev/ Console ' is turned on as standard error output and/or standard output, and '/dev/null ' is used as standard input, or any other method of binding that is meaningful to your daemon. (Translator Note: The general use of the DUP2 function to atomically close and copy file descriptors.)

The implementation code is as follows:

# Core Modules Importatexit importos importsys importtime importsignal Classdaemon (object): "" "A generic daemon 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 self.stdo     UT = 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): "" "Does the UNIX double-fork magic, see Steven S ' "Advanced programming in the UNIX environment" for details (ISBN 0201563177) "" "Try:pid = Os.fork () i  F 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 the parent environment os.chdir (self . Home_dir) Os.setsid() Os.umask (self.umask) # do second fork try:pid = os.fork () If PID > 0: # Exit from S Econd parent sys.exit (0) except OSError, E:sys.stderr.write ("Fork #2 failed:%d (%s) \ n"% (E.E Rrno, E.strerror)) Sys.exit (1) if sys.platform! = ' Darwin ': # This block breaks on OS X # Redirect Standar D file descriptors Sys.stdout.flush () sys.stderr.flush () si = file (Self.stdin, ' r ') so = file (self . StdOut, ' A + ') if Self.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 sigtermhandler (Signum, frame): Self.daemon_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 removed if we quit PID = str (os.getpid ()) file (Self.pidfile, ' w+ '). WR ITE ("%s\n"% pid) def delpid (self): Os.remove (Self.pidfile) def start (self, *args, **kwargs): "" "Start the DA Emon "" "If Self.verbose >= 1:print" Starting ... "# Check for a pidfile-see if the daemon already run       s TRY:PF = file (self.pidfile, ' r ') pid = Int (Pf.read (). Strip ()) Pf.close () except IOError: PID = none except Systemexit: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 # not 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.exis TS (self.pidfile): Os.remove (self.pidfile) else:print str (ERR) sys.exit (1) if Self.ver   Bose >= 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 () ex Cept ioerror:pid = None except Systemexit:pid = None return pid def is_running (self): PID = Self.get_pid () print (PID) return pi D and Os.path.exists ('/proc/%d '% pid) def run (self): "", "" You should override the This method when you subclass Daemon. It would be called after the process had been daemonized by start () or restart (). """

Interested readers can debug and run a sample of this article code, 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.