Python守护进程
Python守护进程
守护进程最重要的特性是后台运行;它必须与其运行前的环境隔离开来,这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录以及文件创建掩码等;它可以在系统启动时从启动脚本/etc/rc.d中启动,可以由inetd守护进程启动,也可以有作业规划进程crond启动,还可以由用户终端(通常是shell)执行。
Python有时需要保证只运行一个脚本实例,以避免数据的冲突。
#!/usr/bin/env python # -*- coding:utf-8 -*- # from: https://www.cnblogs.com/jiangzhaowei/p/6591106.html 适当修改 ''' 功能:将当前进程fork称为一个守护进程 注意:如果你的守护进程是由inetd启动的,不要这样做!inetd完成了,只需要os.chdir 和os.unmask了 ''' import sys,os def daemonize(stdin='/dev/null',stdout='/dev/null',stderr='/dev/null'): #重定向文件描述符,默认情况下定向到/dev/null #1、第一次fork try: fork_result = os.fork() if fork_result > 0 :#说明fork成功,当前进程执行if里面代码,即:结束当前进程,整个代码块继续以子进程身份向下进行运行 sys.exit(0) except OSError as e: sys.stderr.write("fork #1 failed: (%d) %s\n" % (e.errno,e.strerror))#fork失败直接退出 sys.exit(1) #至此没有报错说明到这里已经在第一层子进程中运行,父进程已经退出了,这意味着一个非会话组头领进程永远不能重新获得控制终端。 #从母体环境脱离 os.chdir('/') #chdir 确认进程不保持任何目录于使用状态,否则不能umount一个文件系统。也可以改变到对于守护进程运行重要文件所在目录 os.umask(0) #调用umask(0) 以后便拥有对于任何东西的完全控制,因为有时不知道继承了什么样的umask os.setsid() #调用setid()成功后,进程称为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离 #2、第二次执行fork try: pid = os.fork() if pid > 0: sys.exit(0) except OSError as e: sys.stderr.write('fork #2 failed :%d %s\n'% (e.errno,e.strerror)) sys.exit(1) #到此处进程已经是守护进程了,重定向文件描述符 for f in sys.stdout,sys.stderr: f.flush() si = open(stdin,'r') so = open(stdout,'ab+') se = open(stderr,'ab+',0) #如果 buffering 的值被设为 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(): import time sys.stdout.write('Daemon started with pid %d\n' % os.getpid()) sys.stdout.write('Daemon stdout output \n' ) sys.stderr.write('Daemon stderr output \n' ) c = 0 while True: sys.stdout.write('%d %s\n' % (c,time.ctime())) sys.stdout.flush() c += 1 time.sleep(1) if __name__ == "__main__": daemonize('/dev/null','/tmp/daemon_stdout','/tmp/daemon_stderr') main()
posted on 2019-10-22 20:04 zhangmingda 阅读(297) 评论(0) 编辑 收藏 举报