Python 守护进程打包最佳实践
-
09-09-2019 - |
题
我有一个用 python 编写的工具,通常应该作为守护进程运行。打包此工具进行分发的最佳实践是什么,特别是应如何处理设置文件和守护程序可执行文件/脚本?
相关地,是否有任何通用工具可用于设置守护进程以在启动时运行,以适合给定的平台(即 在里面 Linux 上的脚本,Windows 上的服务, 发射 在 os x 上)?
解决方案
为了回答你的问题的一部分,据我所知,没有任何工具可以跨 Linux 系统进行可移植的守护进程设置,更不用说 Windows 或 Mac OS X 了。
大多数 Linux 发行版似乎都在使用 start-stop-daemon
现在在 init 脚本中,但文件系统布局仍然存在微小差异,而打包方面仍然存在较大差异。如果您的项目全部是 Python,则使用 autotools/configure 或 distutils/easy_install 将大大有助于更轻松地为不同的 Linux/BSD 发行版构建软件包。
Windows 是一个完全不同的游戏,需要 马克·哈蒙德的胜利32 扩展,也许 蒂姆·戈尔登的 WMI 扩展。
我不知道 Launchd,除了“以上都不相关”。
有关守护 Python 脚本的技巧,我会查看在现实世界中实际执行此操作的 Python 应用程序,例如在 Twisted 中。
其他提示
我发现用的init.d脚本帮助最好的工具就是“开始 - 停止 - 守护进程”。它将运行任何应用程序,监视运行/ 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中,我总是建议使用它的一个例子。
互联网上有许多片段提供用纯 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信号。
但我不知道有哪个广泛使用的软件包可以做到这一点。
不是灵丹妙药你问什么,但看看 supervisord 。它处理管理过程中所有的乐趣位。我在一个大的生产环境中大量使用它。此外,它是用Python写的!
我不记得在那里我下载了它......但是这是我找到的最好daemonizing脚本。它精美作品(在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()
你也可以指定地方重定向标准输入输出,呃,等等...
在Linux系统中,系统的包管理器(Portage的为Gentoo,性向为Ubuntu / Debian的,荫为Fedora等)通常需要安装包括将初始化脚本在适当的地方程序照顾。如果你想发布你的Linux程序,你可能想看看捆绑起来成各种分布包管理器的正确格式。
这建议显然是不相关的系统上不具有包管理器(Windows中,和Mac我认为)。
这 博客条目 让我清楚地知道,实际上有两种常见的方法可以让你的Python程序作为守护进程运行(我没有从现有的答案中清楚地弄清楚这一点):
编写守护程序应用程序(例如Python中的服务器)有两种方法。
- 第一个是 处理在python代码中抢劫和停止守护程序的所有任务. 。最简单的方法是与
python-daemon
最终可能进入Python分布的软件包。
波尔加蓬的回答 是第一种方法的示例,尽管它没有使用 python-daemon
包,但链接到一个自定义但非常干净的 python 脚本。
- 另一种方法是 使用操作系统提供的工具. 。在DeBain的情况下,这意味着要编写一个INIT脚本,该脚本利用
start-stop-daemon
程序。
阿里·阿夫沙尔的回答 是第二种方法的 shell 脚本示例,使用 start-stop-daemon
.
我引用的博客文章有一个 shell 脚本示例,以及一些其他详细信息,例如在系统启动时启动守护进程以及在守护进程因任何原因停止时自动重新启动守护进程。
纠正我,但我相信这个问题是如何部署的守护进程。设置您的应用程序通过PIP安装,然后使入口点一个cli(daemon())
。然后创建简单地运行$app_name &
一个初始化脚本
“通常应该被作为守护程序运行?”
不 - 表面上 - 让有很大的意义。 “一般”是不理智的。这是无论是一个守护进程与否。您可能要更新你的问题。
有关守护进程的实例,比如Apache的httpd的或任何数据库服务器(他们是守护进程)或SMTPD邮件守护进程守护程序读取了。
或者,也许,在简单的东西,比如FTP守护阅读起来,SSH服务,远程登录守护进程。
在Linux世界中,你有你的应用程序的安装目录,一些工作目录,加上配置文件目录。
我们使用/opt/ourapp
的应用程序(这是Python,但我们不Python的lib/site-packages
安装)
我们使用/var/ourapp
的工作文件,我们的配置文件。
我们可以使用/etc/ourapp
的配置文件 - 这将是一致的 - 但我们没有
我们不 - 然而 - 使用init.d
脚本启动。但是,这是最后一块,自动启动。现在,我们已经系统管理者启动守护进程。
这是基于,部分地,在 http://www.pathname.com/fhs/和 http://tldp.org/LDP/的Linux文件系统层次/ HTML / Linux的文件系统Hierarchy.html 。