3

我有一个运行多个工作进程的 python 程序。因为这必须正确处理以避免孤立进程,所以我实现了一个信号处理程序来关闭所有工作进程。

该程序或多或少像这样开始:

  1. 启动进程池(启动 X 个工人)
  2. 注册信号处理程序 ( signal.signal(signal.SIGTERM, my_signal_handler))。SIGINT我还为同一个处理程序添加了另一个信号处理程序。
  3. 启动单独的线程轮询后端(数据库)并将任务添加到进程池。
  4. 在主线程上,轮询进程池以获取结果(multiprocessing.Queue单个工作人员将结果添加到结果中)。

这个想法是在 3 和 4 中启动的两个单独的线程保持任务通过机器运行。

如果我手动启动它并调用kill -15 <pid>或者kill -2 <pid>它正确地关闭了一切,等待进程到join(). 从文档中读取,runit 将 a 发送TERM到进程,然后是CONT. 但是,在 runit 下运行它,它只是显示标准ok: down: <my_program>: 1s, normally up,但进程仍在后台运行(即使是主进程,它也是 UNTOUCHED)。

如果我之后出去并手动终止该进程,我可以在日志文件中看到它正确关闭。我究竟做错了什么?似乎 runit 只杀死了我为激活 virtualenv 而创建的 3 行 shell 脚本,但留下了实际的 python 进程。

即使我直接运行“运行”脚本,我也可以运行kill或 Ctrl+C(与 相同SIGINT)并且它会正确关闭。

4

1 回答 1

3

好的,经过一些广泛的测试,我想通了。

Runit 会将终止信号发送到run脚本,默认情况下不会传播它。你需要确保的是你exec python yourscript.py最后打电话。同样,如果您的run脚本调用另一个 shell 脚本(即激活您的 virtualenv 或类似的脚本),它也必须这样做exec

样品:

run

#!/bin/sh
umask 002
2>&1
exec chpst -uanalytics cliscript router

cliscript

#!/bin/sh

# Resolve script path, assuming that the script resides in $(ABSPATH)/bin
SCRIPTPATH="$0"
if [ -h "$SCRIPTPATH" ]; then
    SCRIPTPATH=$(readlink -e "$0")
fi
ABSPATH=$(dirname "$(cd "$(dirname "$SCRIPTPATH")"; pwd -L)")

# Load the virtual environment
source "$ABSPATH/venv/bin/activate"

# Set up environment
export PYTHONUNBUFFERED=1

exec python "$ABSPATH/bin/processing-cli.py" $@

exec当我们将控制权“传递”给下一个脚本或 python 本身时,请注意被调用。

于 2013-08-14T12:26:26.970 回答