【问题标题】:How do I manage a Python based daemon on Linux?如何在 Linux 上管理基于 Python 的守护进程?
【发布时间】:2011-02-26 10:55:06
【问题描述】:

我有一个基于 Python 的工作程序,我想将其作为守护程序运行。目前我正在以一种非常骇人听闻的方式进行操作,从screen-d -m name 会话开始,然后用pkill -9 -f name 杀死它。

最终我不得不将它转移到我们在这里使用的更好的系统(因此我不愿意修改程序)但在此期间,我正在寻找一个更清洁的方式来做到这一点。

我目前的想法是将其作为 inti.d 脚本的后台任务启动,但我如何编写该部分以使其恢复正常?

【问题讨论】:

    标签: python linux bash daemon init.d


    【解决方案1】:

    有些模块可用于守护 Python 脚本。

    python-daemon 实现了良好的守护进程规范 (PEP 3143)。

    还有this module最近出现在github上,它似乎更pythonic且易于使用。

    【讨论】:

      【解决方案2】:

      试试这个question 或更准确的解决方案。

      【讨论】:

      • 我真的不想搞砸程序的内部结构。哎呀,我宁愿保留我现在正在使用的东西,而不是那样做。
      • 真的你不需要改变你的程序,如果它是可导入的。 Joust 在 deamon-example Run 方法中导入您的 main,(替换 while 循环)。
      【解决方案3】:

      在 linux 上有一个 start-stop-daemon 实用程序作为 init.d 工具的一部分。

      它非常灵活,允许以不同的方式捕获服务器的 pid。

      还有一个文件 /etc/init.d/skeleton 可以作为您自己的 init.d 脚本的基础。

      如果您的目标平台是基于 debian 的,那么创建一个 debina 包来部署它是有意义的,因为它还有助于将守护程序正确集成到系统的其余部分中。而且它并不太复杂(如果你之前做过十次的话;-)

      【讨论】:

        【解决方案4】:

        如果你想用 python 中的代码来做,这是一个非常标准的 C 方法,它被移植到我使用的 python 中。它完美无瑕,您甚至可以选择文件输出。

        import os
        import signal
        def daemonize(workingdir='.', umask=0,outfile='/dev/null'):
        #Put in background
        pid = os.fork()
        if pid == 0:
            #First child
            os.setsid()
            pid = os.fork() #fork again
            if pid == 0:
                os.chdir(workingdir)
                os.umask(umask)
            else:
                os._exit(0)
        else:
            os._exit(0)
        
        #Close all open resources
        try:
            os.close(0)
            os.close(1)
            os.close(2)
        except:
            raise Exception("Unable to close standard output. Try running with 'nodaemon'")
            os._exit(1)
        
        #Redirect output
        os.open(outfile, os.O_RDWR | os.O_CREAT)
        os.dup2(0,1)
        os.dup2(0,2)
        

        然后,您可以使用信号来捕获何时向程序发送了终止信号并很好地退出。来自Python Docs的示例

        import signal, os
        
        def handler(signum, frame):
            print 'Signal handler called with signal', signum
            raise IOError("Couldn't open device!")
        
        # Set the signal handler and a 5-second alarm
        signal.signal(signal.SIGALRM, handler)
        signal.alarm(5)
        
        # This open() may hang indefinitely
        fd = os.open('/dev/ttyS0', os.O_RDWR)
        
        signal.alarm(0)          # Disable the alarm
        

        【讨论】:

          【解决方案5】:

          使用init.d 风格的脚本启动它是一个好方法。您可以使用 POSIX 信号将其取下来......请参阅 StackOverflow, Signal handling in Python

          【讨论】:

          • 我可以kill -9 它,但我不知道如何可靠地找到它的PID。
          • @BCS: -9 通常是... 矫枉过正(请原谅双关语)。见kill -9。至于查找它的 PID,您的脚本可以在 /var/run 中创建一个 pidfile,或者使用允许您将 argv[0] 设置为一些易于识别的名称以与 pkill 一起使用的库。
          【解决方案6】:
          猜你喜欢
          • 2012-02-13
          • 1970-01-01
          • 2011-03-06
          • 2023-03-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多