0

我正在通过主管在 schroot 会话中运行 Gunicorn 服务器。我的问题是,当使用“supervisorctl stop”停止服务时,服务并没有完全停止。

这是控制我的服务器的脚本(简化),它在前台运行 gunicorn:

# gunicorn.sh
schroot -c gunicorn -r -- bash -c "gunicorn --workers=1 myapp.wsgi:application" 

这是我运行此脚本的主管配置:

[program:gunicorn]
command=/home/test/gunicorn.sh
stderr_logfile=/var/log/gunicorn.err.log
stdout_logfile=/var/log/gunicorn.out.log 

当我通过 "supervisorctl start" 启动服务时,我的进程树如下所示:

supervisord(7175)---gunicorn.sh(8061)---schroot(8067)---gunicorn(8068)---gunicorn(8073)---{gunicorn}(8078)

现在,当我使用“supervisorctl stop”停止服务时,相应的主管进程及其直接子进程 gunicorn.sh 将被终止。但是 schroot 进程本身继续存在,现在是 init 进程的子进程:

schroot(8067)---gunicorn(8068)---gunicorn(8073)---{gunicorn}(8078)

这整个行为似乎与 schroot 和 gunicorn 的工作方式有关。

如何让主管正确停止我的 schroot 托管进程?

4

2 回答 2

0

必须使用 exec 启动 gunicorn:

# gunicorn.sh
exec schroot -c gunicorn -r -- bash -c "gunicorn --workers=1 myapp.wsgi:application"
于 2014-12-17T19:57:59.630 回答
0

我今天解决了完全相同的问题——但接受的解决方案不起作用。例如这里引用了同样的问题。

使用主管运行程序通常要求您执行的任何操作都使用 exec() 系统调用完成 - 因为它用自己替换原始进程,将 PID(这很重要)留给主管管理(无需从终端分离,当然)。

在 schroot 会话中启动 gunicorn 总是会产生两个进程 - 由主管引用的 schroot - 和 gunicorn master(工人并不重要)。

在主管中调用 stop 只会杀死 schroot 并使 gunicorn master 迁移到 init (PID=1) 使其实际运行。

如果没有 chroot,最简单的方法就是 'exec gunicorn /whatever/'。

我发现似乎没问题的解决方法是这样的:

  1. 使用 pidproxy 帮助程序启动 schroot gunicorn 进程(来自主管分发,/usr/bin/pidproxy)
  2. 将 gunicorn 进程的 PID 写入文件(通常通过修改您的应用程序启动)
  3. 尽可能正确使用 exec。

广告 1. 使用 pidproxy

[program:xxx]
command = pidproxy /path/to/pid/file /path/to/xxx

广告 2. 使用任何方法将 pid 写入文件。我刚刚在我的应用程序启动期间使用了以下代码片段:

pid_file = os.path.join(conf.data_dir, "eventaid.pid")
with open(pid_file, "w") as fout:
    fout.write(str(os.getpid()))

广告 3. 在脚本 /path/to/xxx 中使用 exec

# activate venv
. $HOME/.virtualenvs/python3-xxx/bin/activate
# start within schroot
exec schroot -c jessie -- sh -c "exec gunicorn <whatever>"

现在从主管内部发送 SIGTERM/SIGKILL/... 实际上会将 SIGTERM/SIGKILL/... 发送到 pidproxy,该 pidproxy 会将信号转发给 gunicorn PID,实际上会杀死它。

于 2016-09-13T18:25:10.487 回答