当前位置:天才代写 > tutorial > Python教程 > 用Python实现守护历程

用Python实现守护历程

2017-11-02 08:00 星期四 所属: Python教程 浏览:462

Daemon场景

思量如下场景:你编写了一个python处事措施,而且在呼吁行下启动,而你的呼吁行会话又被终端所节制,python处事成了终端措施的一个子历程。因此假如你封锁了终端,这个呼吁行措施也会随之封锁。 

要使你的python处事不受终端影响而常驻系统,就需要将它酿成守护历程。 

守护历程就是Daemon措施,是一种在系统靠山执行的措施,它独立于节制终端而且执行一些周期任务或触发事件,凡是被定名为"d"字母末了,如常见的httpd、syslogd、systemd和dockerd等。

代码实现

python可以很简捷地实现守护历程,下面给出代码和相应注释。这份代码不变运行在我当地电脑的一个守护历程(廉价闹钟)里,临时没出干涉题。

# coding=utf8
import os
import sys
import atexit
def daemonize(pid_file=None):
    """
    建设守护历程
    :param pid_file: 生存历程id的文件
    :return:
    """
    # 从父历程fork一个子历程出来
    pid = os.fork()
    # 子历程的pid必然为0,父历程大于0
    if pid:
        # 退出父历程,sys.exit()要领比os._exit()要了解多执行一些刷新缓冲事情
        sys.exit(0)
    # 子历程默认担任父历程的事情目次,最好是改观到根目次,不然回影响文件系统的卸载
    os.chdir('/')
    # 子历程默认担任父历程的umask(文件权限掩码),重设为0(完全节制),以免影响措施读写文件
    os.umask(0)
    # 让子历程成为新的会话组长和历程组长
    os.setsid()
    # 留意了,这里是第2次fork,也就是子历程的子历程,我们把它叫为孙子历程
    _pid = os.fork()
    if _pid:
        # 退出子历程
        sys.exit(0)
    # 此时,孙子历程已经是守护历程了,接下来重定向尺度输入、输出、错误的描写符(是重定向而不是封锁, 这样可以制止措施在 print 的时候堕落)
    # 刷新缓冲区先,小心使得万年船
    sys.stdout.flush()
    sys.stderr.flush()
    # dup2函数原子化地封锁和复制文件描写符,重定向到/dev/nul,即扬弃所有输入输出
    with open('/dev/null') as read_null, open('/dev/null', 'w') as write_null:
        os.dup2(read_null.fileno(), sys.stdin.fileno())
        os.dup2(write_null.fileno(), sys.stdout.fileno())
        os.dup2(write_null.fileno(), sys.stderr.fileno())
    # 写入pid文件
    if pid_file:
        with open(pid_file, 'w+') as f:
            f.write(str(os.getpid()))
        # 注册退出函数,历程异常退出时移除pid文件
        atexit.register(os.remove, pid_file)

归纳综合一下守护历程的编写步调:

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

2、子历程改观事情目次(chdir)、文件权限掩码(umask)、历程组和会话组(setsid) 

3、子历程fork孙子历程,退出子历程 

4、孙子历程刷新缓冲,重定向尺度输入/输出/错误(一般到/dev/null,意即扬弃) 

5、(可选)pid写入文件

领略几个要点

为什么要fork两次 

第一次fork,是为了离开终端节制的魔爪。父历程之所以退出,是因为终端敲击键盘、可能封锁时给它发送了信号;而fork出来的子历程,在父历程自杀后成为孤儿历程,进而被操纵系统的init历程经受,因此离开终端节制。 

所以其实,第二次fork并不是必需的(许多开源项目里的代码就没有fork两次)。只不外出于审慎思量,防备历程再次打开一个节制终端。因为子历程此刻是会话组长了(对话期的首次历程),有本领打开节制终端,再fork一次,孙子历程就不能打开节制终端了。

文件描写符 

Linux是“一切皆文件”,文件描写符是内核为已打开的文件所建设的索引,凡是长短负整数。历程通过文件描写符执行IO操纵。 

#p#分页标题#e#

每个历程有本身的文件描写符表,因此沟通的描写符大概指向同一个文件,也大概指向差异文件;来自差异历程的差异的描写符,虽然也有大概指向同一个文件。 

默认环境下,0代表尺度输入,1代表尺度输出,2代表尺度错误。

umask权限掩码 

我们知道,在Linux中,任何一个文件都有读(read)、写(write)和执行(execute)的三种利用权限。个中,读的权限用数字4代表,写权限是2,执行权限是1。呼吁ls -l可以查察文件权限,r/w/x别离暗示具有读/写/执行权限。 

任何文件,也都有用户(User),用户组(Group),其他组(Others)三种身份权限。一般用3个数字暗示文件权限,譬喻754:

7,是User权限,即文件拥有者权限

5,是Group权限,拥有者地址用户组的组员所具有的权限

4,是Others权限,即其他组用户的权限啦

而umask是为了节制默认权限,防备新建文件或文件夹具有全权。 

系统一般默认为022(利用呼吁umask查察),暗示默认建设文件的权限是644,文件夹是755。你应该可以看出它们的纪律,就是文件权限和umask的相加功效为666(笑),文件夹权限和umask的相加功效为777。

历程组 

每个历程都属于一个历程组(PG,Process Group),历程组可以包括多个历程。 

历程组有一个历程组长(Leader),历程组长的ID(PID, Process ID)就作为整个历程组的ID(PGID,Process Groupd ID)。

会话组 

登岸终端时,就会缔造一个会话,多个历程组可以包括在一个会话中。而建设会话的历程,就是会话组长。 

已经是会话组长的历程,不行以再挪用setsid()要领建设会话。因此,上面代码中,子历程可以挪用setsid(),而父历程不能,因为它自己就是会话组长。 

别的,sh(Bourne Shell)不支持会话机制,因为会话机制需要shell支持事情节制(Job Control)。

守护历程与靠山历程 

通过&标记,可以把呼吁放到靠山执行。它与守护历程是差异的:

1、守护历程与终端无关,是被init历程收养的孤儿历程;尔靠山历程的父历程是终端,仍然可以在终端打印

2、守护历程在封锁终端时依然坚挺;尔靠山历程会随用户退出而遏制,除非加上nohup

3、守护历程改变了会话、历程组、事情目次和文件描写符,靠山历程直接担任父历程(shell)的

换句话说:守护历程就是冷静地格斗打拼的有为青年,尔靠山历程是冷静担任老爸资产的富二代。

 

    关键字:

天才代写-代写联系方式