专栏首页python3python 守护进程(daemon)

python 守护进程(daemon)

守护进程的编写步骤:
1、fork子进程,然后父进程退出,此时子进程会被init进程接管。
2、修改子进程的工作目录,创建新进程组合新会话,修改umask。
3、子进程再次fork一个进程,这个进程可以称为孙子进程,然后子进程退出。
4、重定向孙子进程的标准输入流,标准输出流,标准错误到/dev/null

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys, os

'''将当前进程fork为一个守护进程
   注意:如果你的守护进程是由inetd启动的,不要这样做!inetd完成了
   所有需要做的事情,包括重定向标准文件描述符,需要做的事情只有chdir()和umask()了
'''

def daemon(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+')
    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 = c + 1
        time.sleep(1)


if __name__ == "__main__":
    daemone('/dev/null', '/tmp/daemon_stdout.log', '/tmp/daemon_error.log')
    main()

# 可以通过命令ps -ef | grep daemon.py查看后台运行的继承
# 在/tmp/daemon_error.log会记录错误运行日志
# 在/tmp/daemon_stdout.log会记录标准输出日志。

1、fork子进程,父进程退出

通常,我们执行服务端程序的时候都会通过终端连接到服务器,成功连接后会加载shell环境,终端盒shell都是进程,shell进程是终端进程的子进程,通过ps命令可以很容易的查看到,在这个shell环境下一开始执行的程序都是shell进程的子进程,自然会受到shell进程的影响,在程序里fork子进程后,父进程退出,对于shell进程来说,这个父进程就算执行完毕,而产生的子进程会被init进程接管,从而也就脱离了终端控制。

2.修改子进程的工作目录

子进程在创建的时候会继承父进程的工作目录,如果执行的程序是在U盘里面,就会导致U盘不能卸载。

3.创建新会话

使用setsid后,子进程就会成为新会话的首进程,子进程会成为新进程组的组长进程,子进程没有控制终端。

4.修改umask

由于umask会屏蔽权限,所有设定为0,这样可以避免读写文件时碰到权限问题

5.fork孙子进程,子进程退出

经过上面几个步骤后,子进程会成为新的进程组老大,可以重新申请打开终端,为了避免这个问题,fork孙子进程处理,

6.重定向孙子进程的标准输入流,标准输出流,标准错误流到/dev/null

因为是守护进程,本身已经脱离了终端,那么标准输入流,标准输入流,标准错误流就没有什么意义了,所以都转向到/dev/null,就是丢弃的意思

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python守护进程

    假如写一段服务端程序,如果ctrl+c退出或者关闭终端,那么服务端程序就会退出,于是就想着让这个程序成为守护进程,像httpd一样,一直在后端运行,不会受终端影...

    用户2398817
  • python3--进程

    进程的概念起源于操作系统,是操作系统最核心的概念,也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展开的

    用户2398817
  • python3进程和线程

    时间片轮转: 给每个进程分配一个时间片, 如果进程在时间片内执行完就直接执行下一个进程, 如果没执行完, 进程释放CPU给下一个进程 优先级队列: 在优先级队列...

    用户2398817
  • 操作系统学习笔记-3:进程

    之前的单道批处理系统,程序是串行执行的,内存中可能只需要记录单一程序的程度段和数据段即可;但是现在使用的是多道批处理系统,多个程序并发执行,内存中就可能存在多个...

    Chor
  • 操作系统-进程

    (2)阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。

    CherishTheYouth
  • linux进程调度

    Mister24
  • Python标准库11 多进程探索 (multiprocessing包)

    在初步了解Python多进程之后,我们可以继续探索multiprocessing包中更加高级的工具。这些工具可以让我们更加便利地实现多进程。 进程池 进程池 (...

    Vamei
  • Python 学习入门(24)—— 进程高级

    初步了解Python多进程之后,我们可以继续探索multiprocessing包中更加高级的工具。这些工具可以让我们更加便利地实现多进程。

    阳光岛主
  • Java中的定时任务

    现代的应用程序早已不是以前的那些由简单的增删改查拼凑而成的程序了,高复杂性早已是标配,而任务的定时调度与执行也是对程序的基本要求了。

    Single
  • 进程管理利器-supervisor部署记录

    一、简单介绍 supervisor是用来管理进程的一个工具,止于为什么要用supervisor,是因为相对于linux传统的进程管理方式来说,它有很多的优势: ...

    洗尽了浮华

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动