我有一个用python编写的工具,通常应该作为守护进程运行。打包此工具以进行分发的最佳实践是什么,特别是如何处理设置文件和守护程序可执行文件/脚本?
相关的是,有任何常用的工具可以设置守护进程在启动时运行,以适合给定的平台(即Linux上的 init 脚本,Windows上的服务, launchd 在os x)?
答案 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守护进程函数相同。
基本上:
一开始:
停止:
我不知道有任何广泛使用的包这样做。
答案 3 :(得分:5)
检查Ben Finney的守护进程模块。他已经开始编写一个针对python 3.X的PEP:
http://www.python.org/dev/peps/pep-3143/
但是这里已经有了一个实现:
答案 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 &
答案 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。