轻松创建python守护进程

守护进程是脱离于终端并且在后台运行的进程,脱离终端是为了避免在执行的过程中的信息在终端上显示,并且进程也不会被任何终端所产生的终端信息所打断,想要在linux系统下开启一个守护进程,可以使用nohup python task.py & 的方式,这种方法虽然可行,但有其不方便之处

  1. 启动后不能方便的查看进程状态
  2. kill进程时只能先使用ps命令查看进程pid ,然后使用kill 命令来杀掉进程
  3. nohup方式不能保证一个任务只有一个进程,多次使用,便会产生多个进程,这对于只能有一个进程的任务来说是危险的。

想要轻松的创建python守护进程,推荐使用service模块,它是基于 python-daemon 库构建的,提供了更加灵活的操作方式,使用pip进行安装

pip install service

编写task.py脚本,内容如下

import time
import sys
from service import Service

def my_task():
    """
    这是你的任务
    """
    for i in range(10):
        print('ok')
        time.sleep(5)


class TaskService(Service):
    def __init__(self, *args, **kwargs):
        super(TaskService, self).__init__(*args, **kwargs)

    def run(self):
        my_task()

if __name__ == '__main__':

    if len(sys.argv) != 2:
        sys.exit('Syntax: %s COMMAND' % sys.argv[0])

    cmd = sys.argv[1].lower()
    service = TaskService('my_service', pid_dir='/tmp')

    if cmd == 'start':
        service.start()
    elif cmd == 'stop':
        service.stop()
    elif cmd == 'kill':
        service.kill()
    elif cmd == 'pid':
        print(service.get_pid())
    elif cmd == 'status':
        if service.is_running():
            print("Service is running.")
        else:
            print("Service is not running.")
    else:
        sys.exit('Unknown command "%s".' % cmd)

创建一个Service对象时,需要指定服务的name, 同一个name只会存在一个守护进程, pid_dir默认的目录是/var/run, 进程启动后会产生一个my_service.pid的文件,文件中的内容正是守护进程的pid,当进程结束时,这个文件也会被删除。

stop方法和kill方法的区别在于,stop方法会发送SIGTERM, 这个信号是可以被进程忽略的,进程也可以接收这个信号去做一些收尾工作然后再推出,而kill方法发送的SIGKILL命令,进程会立即终止,这是一个非常稳定的终止进程的方法。

如果你使用了service启动守护进程,那么一定要使用service提供的stop或者kill来终止进程,倘若你直接使用kill -9 pid的方式终止进程,那么个my_service.pid就不会被删除,下一次启动时就会报错,service是根据是否存在my_service.pid文件来判断进程是否存在的。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案