victory的博客

长安一片月,万户捣衣声

0%

python | 守护进程

python第三方库/python-daemon/将当前进程变为守护进行

  • 守护进程

    • 什么是守护进程?

      守护进程是一种在后台运行的进程,通常用于执行周期性或长时间运行的任务。

    • 特点:

      • 在后台运行的进程
      • 没有控制终端(不受键盘、tty影响)
  • 守护进程的原始实现

    • 守护进程实现核心步骤
      • fork() 一个子进程,父进程退出(脱离原始终端)
      • setsid() 创建新会话,脱离控制终端
      • 第二次 fork() 防止重新获得终端
      • chdir(‘/‘) 切换到根目录(避免锁定工作目录)
      • umask(0) 重设文件权限掩码
      • 重定向 stdin、stdout、stderr 到 /dev/null
  • 实现守护进程的方法

    • 方法1

      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
      import os
      import sys

      def daemonize():
      # 第一次 fork
      pid = os.fork()
      if pid > 0:
      sys.exit(0)

      # 脱离终端,创建新会话
      os.setsid()
      os.umask(0)

      # 第二次 fork,避免重新打开终端
      pid = os.fork()
      if pid > 0:
      sys.exit(0)

      # 关闭标准文件描述符并重定向到 /dev/null
      sys.stdout.flush()
      sys.stderr.flush()
      with open('/dev/null', 'rb', 0) as f:
      os.dup2(f.fileno(), sys.stdin.fileno())
      with open('/dev/null', 'ab', 0) as f:
      os.dup2(f.fileno(), sys.stdout.fileno())
      os.dup2(f.fileno(), sys.stderr.fileno())
    • 方法2(推荐使用)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      import daemon

      def run():
      while True:
      # 你的后台任务代码
      ...

      with daemon.DaemonContext():
      run()
    • 方法3:使用multiprocessing模块

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      from multiprocessing import Process, current_process

      def task():
      process = current_process()
      print(f"Daemon process: {process.daemon}")

      if __name__ == "__main__":
      process = Process(target=task, daemon=True)
      process.start()
      process.join()
  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import time
    import daemon
    from daemon import pidfile

    LOG_PATH = "/tmp/my_daemon.log"
    PID_PATH = "/tmp/my_daemon.pid"

    def run():
    while True:
    with open(LOG_PATH, "a") as f:
    f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Daemon is running...\n")
    time.sleep(5)

    if __name__ == "__main__":
    with daemon.DaemonContext(
    working_directory=".",
    umask=0o002,
    pidfile=pidfile.TimeoutPIDLockFile(PID_PATH)
    ):
    run()