python-daemon是一个Python的第三方库。
其核心功能是创建一个Daemon进程(后台运行以及脱离当前父进程管控)
本文中,我们将会基于如上两个场景进行分析。
安装
python-daemon可以直接使用pip
命令进行安装,安装方式如下:
pip install python-daemon
场景1:程序后台运行
很多时候,我们希望我们的程序能够后台执行。
此时,一些常用的方法是nohup .... &
,这类方法其实并不优雅。
下面,我们来讲解如何使用python-daemon
模块来编写一个原生后台执行的服务。
编写daemon2.py
文件如下:
#-*- coding: UTF-8 -*-
import time
import logging
import logging.handlers
from daemon import runner
class App(object):
"""
# 定义一个应用
"""
def __init__(self):
"""
# 设置标准输入,标准输出,pid文件等
"""
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/tmp/foo.pid'
self.pidfile_timeout = 5
def run(self):
"""
# 应用启动入口函数
"""
# 设置日志打印规则
logs = logging.getLogger('MyLogger')
logs.setLevel(logging.DEBUG)
fh = logging.handlers.RotatingFileHandler(
'/tmp/test.log',maxBytes=10000000,backupCount=5)
fh.setLevel(logging.DEBUG)
formatter = logging.Formatter(u'%(asctime)s [%(levelname)s] %(message)s')
fh.setFormatter(formatter)
logs.addHandler(fh)
# 主程序
while True:
for i in range(10):
logs.info("Beginning Scan {0}! \n".format(i))
time.sleep(1)
# 整个程序的入口
app = App()
daemon_runner = runner.DaemonRunner(app)
daemon_runner.do_action()
该程序的启动方式如下:
usage: daemon2.py start|stop|restart
因此,可以通过该程序直接进行启动、停止、重启等操作。
场景2:程序脱离当前父进程管控
除了程序后台运行外,有时我们在一个应用中可以会从主进程fork出多个子进程。
此时,一旦主进程发生重启等操作,所有的子进程均会受到影响导致退出。因此,如果我们希望子进程不受到主进程影响的话,需要让fork出的子进程脱离父进程管控,从而当父进程退出后,子进程不受影响。
demo示例如下:
# -*- coding: UTF-8 -*-
import os
import time
import daemon
from logzero import logger
# 首先进行一次fork,防止对原有进程产生干扰
pid = os.fork()
if pid == 0:
# 对于fork出的子进程,进入Daemon模式
with daemon.DaemonContext():
try:
import setproctitle
setproctitle.setproctitle("[TaskDaemon:1]")
except ImportError as e:
logger.warning("setproctitle module not found")
time.sleep(3600)
else:
# 对于父进程(原始进程),保留原有逻辑执行
return 0