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   zhangmingda  阅读(299)  评论(0编辑  收藏  举报

编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示