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)
    
  • 相关阅读:
    删数问题
    八中公司_二分图带权最大匹配模板题
    完美子图(这道题太难了,得写下来要不回头又忘了)
    最近集训的图论(思路+实现)题目汇总(内容包含tarjan、分层图、拓扑、差分、奇怪的最短路):
    方格取数(简单版)+小烈送菜(不知道哪来的题)-----------奇怪的dp增加了!
    单调队列优化题:最大数(P1198)
    单调队列+线性dp题Watching Fireworks is Fun (CF372C)
    关于看了几道洛谷灰题(暂无评定)的感想
    洛谷的奇妙今日运势
    互不侵犯(洛谷P1896)
  • 原文地址:https://www.cnblogs.com/KevinGeorge/p/9260145.html
Copyright © 2011-2022 走看看