Python守护程序包装最佳实践

时间:2009-02-26 01:32:40

标签: python packaging setuptools distutils

我有一个用python编写的工具,通常应该作为守护进程运行。打包此工具以进行分发的最佳实践是什么,特别是如何处理设置文件和守护程序可执行文件/脚本?

相关的是,有任何常用的工具可以设置守护进程在启动时运行,以适合给定的平台(即Linux上的 init 脚本,Windows上的服务, launchd 在os x)?

10 个答案:

答案 0 :(得分:14)

我找到的帮助init.d脚本的最佳工具是“start-stop-daemon”。它将运行任何应用程序,监视运行/ pid文件,在必要时创建它们,提供停止守护程序的方法,设置进程用户/组ID,甚至可以为您的进程提供后台。

例如,这是一个可以启动/停止wsgi服务器的脚本:

#! /bin/bash

case "$1" in
  start)
    echo "Starting server"

    # Activate the virtual environment
    . /home/ali/wer-gcms/g-env/bin/activate

    # Run start-stop-daemon, the $DAEMON variable contains the path to the
    # application to run
    start-stop-daemon --start --pidfile $WSGI_PIDFILE \
        --user www-data --group www-data \
        --chuid www-data \
        --exec "$DAEMON"
    ;;
  stop)
    echo "Stopping WSGI Application"

    # Start-stop daemon can also stop the application by sending sig 15
    # (configurable) to the process id contained in the run/pid file
    start-stop-daemon --stop --pidfile $WSGI_PIDFILE --verbose
    ;;
  *)
    # Refuse to do other stuff
    echo "Usage: /etc/init.d/wsgi-application.sh {start|stop}"
    exit 1
    ;;
esac

exit 0

你还可以看到一个如何将它与virtualenv一起使用的例子,我总是建议这样做。

答案 1 :(得分:11)

为了回答你问题的一部分,我知道没有任何工具可以在Linux系统上轻松设置守护进程,更不用说Windows或Mac OS X.

大多数Linux发行版现在似乎在init脚本中使用start-stop-daemon,但是你仍然会在文件系统布局和包装方面存在很大差异。如果你的项目都是Python,那么使用autotools / configure或distutils / easy_install将大大有助于为不同的Linux / BSD发行版构建软件包。

Windows是一款完全不同的游戏,需要Mark Hammond's win32个扩展程序,可能需要Tim Golden's WMI个扩展程序。

我不知道Launchd,除了“以上都不是”是相关的。

有关守护Python脚本的提示,我会查看在现实世界中实际执行此操作的Python应用程序,例如在Twisted内部。

答案 2 :(得分:8)

互联网上有许多片段用于在纯python中编写守护进程(无bash脚本)

http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/ 看起来很干净......

如果你想自己写,
原理与bash守护进程函数相同。

基本上:

一开始:

  • 你分叉到另一个进程
  • 打开日志文件以重定向您的 stdout和stderr
  • 在某个地方保存pid。

停止:

  • 您将SIGTERM发送到存储在您的pid文件中的pid的进程。
  • 使用signal.signal(signal.SIGTERM,sigtermhandler),你可以绑定一个停止 SIGTERM信号的程序。

我不知道有任何广泛使用的包这样做。

答案 3 :(得分:5)

检查Ben Finney的守护进程模块。他已经开始编写一个针对python 3.X的PEP:

http://www.python.org/dev/peps/pep-3143/

但是这里已经有了一个实现:

http://pypi.python.org/pypi/python-daemon/

答案 4 :(得分:4)

不是你问的问题,但请查看supervisord。它处理管理流​​程的所有有趣内容。我在大型生产环境中大量使用它。另外,它是用Python编写的!

答案 5 :(得分:3)

我不记得我在哪里下载了它...但这是我发现的最好的守护程序脚本。它工作得很漂亮(在Mac和Linux上。)(保存为daemonize.py)

import sys, os
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
    # Perform first fork.
    try:
        pid = os.fork( )
        if pid > 0:
            sys.exit(0) # Exit first parent.
    except OSError, e:
        sys.stderr.write("fork #1 failed: (%d) %sn" % (e.errno, e.strerror))
        sys.exit(1)
    # Decouple from parent environment.
    os.chdir("/")
    os.umask(0)
    os.setsid( )
    # Perform second fork.
    try:
        pid = os.fork( )
        if pid > 0:
            sys.exit(0) # Exit second parent.
    except OSError, e:
        sys.stderr.write("fork #2 failed: (%d) %sn" % (e.errno, e.strerror))
        sys.exit(1)
    # The process is now daemonized, redirect standard file descriptors.
    for f in sys.stdout, sys.stderr: f.flush( )
    si = file(stdin, 'r')
    so = file(stdout, 'a+')
    se = file(stderr, 'a+', 0)
    os.dup2(si.fileno( ), sys.stdin.fileno( ))
    os.dup2(so.fileno( ), sys.stdout.fileno( ))
    os.dup2(se.fileno( ), sys.stderr.fileno( ))

在您的脚本中,您只需:

from daemonize import daemonize
daemonize()

你还可以指定重定向stdio,err等的地方......

答案 6 :(得分:0)

在Linux系统上,系统的包管理器(Gentoo的Portage,Ubuntu / Debian的Aptitude,Fedora的yum等)通常负责安装程序,包括将init脚本放在正确的位置。如果要分发Linux程序,可能需要考虑将其捆绑为各种发行版程序包管理器的正确格式。

这个建议显然与没有包管理器的系统无关(我认为是Windows和Mac)。

答案 7 :(得分:0)

这个blog entry让我清楚地知道,实际上有两种常见的方法可以让你的Python程序作为一个守护程序运行(我没有从现有的答案中清楚地看出这一点):

  

编写守护程序应用程序(如服务器)有两种方法   在Python中。

     
      
  • 首先是处理所有的sarting和   用Python代码本身停止守护进程。最简单的方法是   使用python-daemon包可能最终成功   进入Python发行版。
  •   

Poeljapon's answer是第一种方法的一个例子,虽然它不使用python-daemon包,但链接到自定义但非常干净的python脚本。

  
      
  • 另一种方法是使用这些工具   由操作系统提供。在Debain的情况下,这意味着   编写一个使用start-stop-daemon的init脚本   程序
  •   

Ali Afshar's answer是第二种方法的shell脚本示例,使用start-stop-daemon

我引用的博客条目有一个shell脚本示例,以及一些其他详细信息,例如在系统启动时启动守护程序,并在因任何原因停止时自动重启守护程序。

答案 8 :(得分:0)

如果错误,请纠正我,但我相信问题是如何部署守护进程。将您的应用设置为通过pip安装,然后将entry_point设为cli(daemon())。然后创建一个只运行$app_name &

的init脚本

答案 9 :(得分:-11)

“通常应该作为守护进程运行?”

不 - 表面上 - 很有意义。 “一般”是不明智的。它或者是一个守护进程。您可能想要更新您的问题。

有关守护进程的示例,请阅读Apache的httpd或任何数据库服务器(它们是守护程序)或SMTPD邮件守护程序等守护进程。

或者,也许,读一些更简单的东西,比如FTP守护进程,SSH守护进程,Telnet守护进程。

在Linux世界中,您将拥有应用程序安装目录,一些工作目录以及配置文件目录。

我们对应用程序使用/opt/ourapp(它是Python,但我们不在Python的lib/site-packages中安装)

我们将/var/ourapp用于工作文件和配置文件。

我们可以将/etc/ourapp用于配置文件 - 它会保持一致 - 但我们没有。

我们还没有 - 使用init.d脚本进行启动。但那是最后一块,自动化的启动。现在,我们让sys管理员启动守护进程。

部分基于http://www.pathname.com/fhs/http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/Linux-Filesystem-Hierarchy.html