2009-02-26 53 views
23

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

与此相关的是有用于设置守护程序在启动时运行的适合特定平台的任何常用的工具(在Linux上即初始化脚本,服务在Windows,OS X上的launchd)?

+1

另请参阅此SO问题:http://stackoverflow.com/questions/473620/how-do-you-create-a-daemon-in-python – Rabarberski 2012-01-11 09:42:43

回答

11

要回答你的问题的一部分,没有工具,我知道的,会做可移植甚至跨Linux系统守护进程设置更不用说Windows或Mac OS X.

大多数Linux发行版似乎可以用start-stop-daemon内init脚本,但是你仍然会在文件系统布局上有细微的差别,在包装上也有很大的差异。如果你的项目都是Python,使用autotools/configure或者distutils/easy_install将会大大简化为不同的Linux/BSD发行版构建软件包的过程。

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

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

关于守护Python脚本的提示,我会看看实际在真实世界中执行它的Python应用程序,例如Twisted内部。

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中,我总是建议使用它的一个例子。 “一般应该作为一个守护进程运行?”

-10

不 - 在表面上 - 有很大的意义。 “一般”不明智。它不是一个守护进程就是一个守护进程。你可能想更新你的问题。

有关守护程序的示例,请阅读诸如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

+2

你很漂亮强硬!? 守护进程只是守护进程的程序。有时将它们作为Ctrl-C的常规进程运行会很有用,请检查stdout上的输出等。 – fulmicoton 2009-02-26 02:15:32

+0

@Paul:同意。你能澄清这个问题吗? – 2009-02-26 02:21:41

0

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

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

+0

有很多其他Unices的包装系统!例如NetBSD的pkgsrc。 – bortzmeyer 2009-02-26 08:57:52

+0

有趣的是,我不知道 – 2009-02-26 17:54:37

8

有在互联网上提供许多片段写在纯Python守护程序(没有的bash脚本)

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

如果你想编写自己的,
的原理与bash守护进程功能相同。

基本上是:

在启动:

  • 你叉到另一个进程
  • 打开日志文件到PID某处重定向你 输出和错误
  • 保存。

在车站:

  • 您发送SIGTERM到进程的PID与存储在您的pidfile进程文件。
  • 使用signal.signal(signal.SIGTERM,sigtermhandler),您可以将停止 过程绑定到SIGTERM信号。

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

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() 

而且你还可以指定地方重定向标准输入输出,错误等...

3

不是你问什么银弹,但检查出supervisord。它处理管理流​​程的所有有趣部分。我在大型生产环境中大量使用它。另外,它是用Python编写的!

0

blog entry清楚对我来说其实有让你的Python程序作为deamon运行的两种常见方法(我没有从现有的答案中清楚地看出):

有两种方法可以在Python中编写像服务器 这样的守护进程应用程序。

  • 首先是手柄sarting的所有任务,并在Python代码本身 停止守护进程。最简单的方法是使用 和python-daemon软件包,它最终可能会将 转换为Python发行版。

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

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

Ali Afshar's answer是第二方法的一个外壳脚本例如,使用start-stop-daemon

的博客中我引用了一个shell脚本例子,在一些事情的更多详细信息,例如在系统启动时启动您的守护进程,并自动重新启动守护进程时,它停止以任何理由。

0

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