zoukankan      html  css  js  c++  java
  • Python守护进程和脚本单例运行

    Python 守护进程


    守护进程简介

    进程运行有时候需要脱离当前运行环境,尤其是Linux和Unix环境中需要脱离Terminal运行,这个时候就要用到守护进程。守护进程可以脱离当前环境要素来执行,这些要素包括:未关闭的文件描述符、控制终端、会话和进程组、工作目录以及文件创建掩码等

    流程梳理

    为了实现守护进程的功能,需要做以下几步:(1)fork一个新的进程,如果新的进程pid大于0,sys.exit(0),如果有异常,处理后退出即可;(2)脱离母体,切换到根目录下,设置os.umask(0)以便于获取高的读写权限。然后设置自己成为新的进程和回话组长,os.setsid();(3)然后尝试执行第二次fork进程,与第一步一致;(4)重定向标准文件描述符

    函数实现

    
    #!/usr/bin/env python
    #coding: utf-8
    import sys, os
     
    '''将当前进程fork为一个守护进程
       注意:如果你的守护进程是由inet.d启动的,不要这样做!inet.d完成了
       所有需要做的事情,包括重定向标准文件描述符,需要做的事情只有chdir()和umask()了
    '''
     
    def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
         #重定向标准文件描述符(默认情况下定向到/dev/null)
        try: 
            pid = os.fork() 
              #父进程(会话组头领进程)退出,这意味着一个非会话组头领进程永远不能重新获得控制终端。
            if pid > 0:
                sys.exit(0)   #父进程退出
        except OSError, e: 
            sys.stderr.write ("fork #1 failed: (%d) %s
    " % (e.errno, e.strerror) )
            sys.exit(1)
     
         #从母体环境脱离
        os.chdir("/")  #chdir确认进程不保持任何目录于使用状态,否则不能umount一个文件系统。也可以改变到对于守护程序运行重要的文件所在目录
        os.umask(0)    #调用umask(0)以便拥有对于写的任何东西的完全控制,因为有时不知道继承了什么样的umask。
        os.setsid()    #setsid调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。
     
         #执行第二次fork
        try: 
            pid = os.fork() 
            if pid > 0:
                sys.exit(0)   #第二个父进程退出
        except OSError, e: 
            sys.stderr.write ("fork #2 failed: (%d) %s
    " % (e.errno, e.strerror) )
            sys.exit(1)
     
         #进程已经是守护进程了,重定向标准文件描述符
     
        for f in sys.stdout, sys.stderr: f.flush()
        si = open(stdin, 'r')
        so = open(stdout, 'a+')
        se = open(stderr, 'a+', 0)
        os.dup2(si.fileno(), sys.stdin.fileno())    #dup2函数原子化关闭和复制文件描述符
        os.dup2(so.fileno(), sys.stdout.fileno())
        os.dup2(se.fileno(), sys.stderr.fileno())
    
    def main(): 
        do_something()
    if __name__ == "__main__":
        daemonize()
        main()
    

    单例脚本运行


    原理

    打开文件本身加锁,加一个排它锁,通过锁机制来保证单例运行。

    
    #!/usr/bin/env python
    #coding: utf-8
    import fcntl, sys, time, os
    pidfile = 0
     
    def ApplicationInstance():
        global pidfile
        pidfile = open(os.path.realpath(__file__), "r")
        try:
            fcntl.flock(pidfile, fcntl.LOCK_EX | fcntl.LOCK_NB) #创建一个排他锁,并且所被锁住其他进程不会阻塞
        except:
            print "another instance is running..."
            sys.exit(1)
     
    if __name__ == "__main__":
        ApplicationInstance()
        while True:
            print 'running...'
            time.sleep(1)
    
  • 相关阅读:
    Python正则表达式如何正确运用?七大案例详解
    Python爬虫的谷歌Chrome F12如何抓包分析?案例详解
    Python的Cookie如何正确操作运用呢?案例详解
    八大Python爬虫技巧,你会几个?
    Python爬虫解析神器-正则表达式如何正确运用?案例详解
    Python爬虫之Selector的基本用法正确运用方法,案例详解
    Python爬虫是如何遍历文档树呢?一招教你
    Python之Selenium如何正确运用?案例详解
    Python中的单例模式如何正确运用?本文详解
    JAVA-Spring 整合 JDBC
  • 原文地址:https://www.cnblogs.com/KevinGeorge/p/9260145.html
Copyright © 2011-2022 走看看