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\n" % (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\n" % (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)

最新文章

  1. Git Bash的一些命令和配置
  2. java JSP(原创新手可进)
  3. Issue 3:数据处理基本认识
  4. IBatis一对多查询
  5. Unity3D 系统宏
  6. JAVA基础学习day16--集合三-Map、HashMap,TreeMap与常用API
  7. 【python游戏编程之旅】第四篇---pygame中加载位图与常用的数学函数。
  8. [Ubuntu] Ubuntu DNS服务器配置
  9. Linux的启动过程
  10. [二]Json-lib的用法
  11. dubbo资料
  12. python google play
  13. iOS面试题整理(一)
  14. 用c#在Access数据库中创建新表
  15. JavaScript-DOM编程的一些常用属性
  16. Java学生成绩
  17. 安装与配置apache WEB服务器(Linux环境)
  18. httpd服务器的真实ip获取难题
  19. 面试:C++输入数据
  20. 统计学习方法c++实现之六 支持向量机(SVM)及SMO算法

热门文章

  1. iOS : 判断运行设备类型是否是iPad
  2. 8.1 shell介绍 8.2 命令历史 8.3 命令补全和别名 8.4 通配符 8.5 输入输出重定向 
  3. 5.5 进入编辑模式 5.6 vim命令模式 5.7 vim实践
  4. 多个table 相同col 的 设置相同width
  5. 【Intel AF 2.1 学习笔记二】AF中的页面——Panel
  6. centos 离线安装Ambari
  7. linux下使用yum安装 mencached
  8. layer的用法
  9. AngularJS------报错"The selector "app-user-item" did not match any elements"
  10. eclipse debug Liunx服务器上的svn项目