最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

Python实现Linux下守护进程的编写方法

来源:懂视网 责编:小采 时间:2020-11-27 14:38:14
文档

Python实现Linux下守护进程的编写方法

Python实现Linux下守护进程的编写方法:本文实例讲述了Python实现Linux下守护进程的编写方法,分享给大家供大家参考,相信对于大家的Python程序设计会起到一定的帮助作用。具体方法如下: 1. 调用fork()以便父进程可以退出,这样就将控制权归还给运行你程序的命令行或shell程序。需要这一步以便
推荐度:
导读Python实现Linux下守护进程的编写方法:本文实例讲述了Python实现Linux下守护进程的编写方法,分享给大家供大家参考,相信对于大家的Python程序设计会起到一定的帮助作用。具体方法如下: 1. 调用fork()以便父进程可以退出,这样就将控制权归还给运行你程序的命令行或shell程序。需要这一步以便

本文实例讲述了Python实现Linux下守护进程的编写方法,分享给大家供大家参考,相信对于大家的Python程序设计会起到一定的帮助作用。具体方法如下:

1. 调用fork()以便父进程可以退出,这样就将控制权归还给运行你程序的命令行或shell程序。需要这一步以便保证新进程不是一个进程组头领进程(process group leader)。下一步,‘setsid()',会因为你是进程组头领进程而失败。进程调用fork函数时,操作系统会新建一个子进程,它本质上与父进程完全相同。子进程从父进程继承了多个值的拷贝,比如全局变量和环境变量。两个进程唯一的区别就是fork的返回值。child(子)进程接收返回值为0,而父进程接收子进程的pid作为返回值。调用fork函数后,两个进程并发执行同一个程序,首先执行的是调用了fork之后的下一行代码。父进程和子进程既并发执行,又相互独立;也就是说,它们是“异步执行”的。

2. 调用‘setsid()' 以便成为一个进程组和会话组的头领进程。由于一个控制终端与一个会话相关联,而且这个新会话还没有获得一个控制终端,我们的进程没有控制终端,这对于守护程序来说是一件好事。

3. 再次调用‘fork()'所以父进程(会话组头领进程)可以退出。这意味着我们,一个非会话组头领进程永远不能重新获得控制终端。

4. 调用‘chdir("/")'确认我们的进程不保持任何目录于使用状态。不做这个会导致系统管理员不能卸装(umount)一个文件系统,因为它是我们的当前工作目录。 [类似的,我们可以改变当前目录至对于守护程序运行重要的文件所在目录]

5. 调用‘umask(0)'以便我们拥有对于我们写的任何东西的完全控制。我们不知道我们继承了什么样的umask。 [这一步是可选的](译者注:这里指步骤5,因为守护程序不一定需要写文件)

6. 调用‘close()'关闭文件描述符0,1和2。这样我们释放了从父进程继承的标准输入,标准输出,和标准错误输出。我们没办法知道这些文描述符符可能已经被重定向去哪里。注意到许多守护程序使用‘sysconf()'来确认‘_SC_OPEN_MAX'的限制。‘_SC_OPEN_MAX'告诉你每个进程能够打开的最多文件数。然后使用一个循环,守护程序可以关闭所有可能的文件描述符。你必须决定你需要做这个或不做。如果你认为有可能有打开的文件描述符,你需要关闭它们,因为系统有一个同时打开文件数的限制。

7. 为标准输入,标准输出和标准错误输出建立新的文件描述符。即使你不打算使用它们,打开着它们不失为一个好主意。准确操作这些描述符是基于各自爱好;比如说,如果你有一个日志文件,你可能希望把它作为标准输出和标准错误输出打开,而把‘/dev/null'作为标准输入打开;作为替代方法,你可以将‘/dev/console'作为标准错误输出和/或标准输出打开,而‘/dev/null'作为标准输入,或者任何其它对你的守护程序有意义的结合方法。(译者注:一般使用dup2函数原子化关闭和复制文件描述符。

实现代码如下:

# 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.stdout = 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): 
 """ 
Do the UNIX double-fork magic, see Stevens' "Advanced 
Programming in the UNIX Environment" for details (ISBN 0201563177) 
""" 
 try: 
 pid = os.fork() 
 if pid > 0: 
 # Exit first parent 
 sys.exit(0) 
 except OSError, e: 
 sys.stderr.write( 
 "fork #1 failed: %d (%s)
" % (e.errno, e.strerror)) 
 sys.exit(1) 
 # Decouple from 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 second parent 
 sys.exit(0) 
 except OSError, e: 
 sys.stderr.write( 
 "fork #2 failed: %d (%s)
" % (e.errno, e.strerror)) 
 sys.exit(1) 
 if sys.platform != 'darwin': # This block breaks on OS X 
 # Redirect standard 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+').write("%s
" % pid) 
 def delpid(self): 
 os.remove(self.pidfile) 
 def start(self, *args, **kwargs): 
 """ 
Start the daemon 
""" 
 if self.verbose >= 1: 
 print "Starting..." 
 # Check for a pidfile to see if the daemon already runs 
 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?
" 
 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?
" 
 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 % 10 == 0: 
 os.kill(pid, signal.SIGHUP) 
 except OSError, err: 
 err = str(err) 
 if err.find("No such process") > 0: 
 if os.path.exists(self.pidfile): 
 os.remove(self.pidfile) 
 else: 
 print str(err) 
 sys.exit(1) 
 if self.verbose >= 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() 
 except IOError: 
 pid = None 
 except SystemExit: 
 pid = None 
 return pid 
 def is_running(self): 
 pid = self.get_pid() 
 print(pid) 
 return pid and os.path.exists('/proc/%d' % pid) 
 def run(self): 
 """ 
You should override this method when you subclass Daemon. 
It will be called after the process has been 
daemonized by start() or restart(). 
"""

感兴趣的读者可以调试运行一下本文实例代码,相信会有新的收获。

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

Python实现Linux下守护进程的编写方法

Python实现Linux下守护进程的编写方法:本文实例讲述了Python实现Linux下守护进程的编写方法,分享给大家供大家参考,相信对于大家的Python程序设计会起到一定的帮助作用。具体方法如下: 1. 调用fork()以便父进程可以退出,这样就将控制权归还给运行你程序的命令行或shell程序。需要这一步以便
推荐度:
标签: linux 编写 python
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top