【问题标题】:Supervisor fails to restart half of the timeSupervisor 有一半时间无法重启
【发布时间】:2015-12-20 16:52:04
【问题描述】:

我正在尝试在运行 Debian 8.1 的机器上使用 Uwsgi 和主管部署 Django 应用程序。

当我通过sudo systemctl restart supervisor 重新启动时,有一半时间无法重新启动。

$ root@host:/# systemctl start supervisor
    Job for supervisor.service failed. See 'systemctl status supervisor.service' and 'journalctl -xn' for details.
$ root@host:/# systemctl status supervisor.service
    ● supervisor.service - LSB: Start/stop supervisor
       Loaded: loaded (/etc/init.d/supervisor)
       Active: failed (Result: exit-code) since Wed 2015-09-23 11:12:01 UTC; 16s ago
      Process: 21505 ExecStop=/etc/init.d/supervisor stop (code=exited, status=0/SUCCESS)
      Process: 21511 ExecStart=/etc/init.d/supervisor start (code=exited, status=1/FAILURE)
    Sep 23 11:12:01 host supervisor[21511]: Starting supervisor:
    Sep 23 11:12:01 host systemd[1]: supervisor.service: control process exited, code=exited status=1
    Sep 23 11:12:01 host systemd[1]: Failed to start LSB: Start/stop supervisor.
    Sep 23 11:12:01 host systemd[1]: Unit supervisor.service entered failed state.

但是,主管或 uwsgi 日志中没有任何内容。 Supervisor 3.0 正在使用 uwsgi 的此配置运行:

[program:uwsgi]
stopsignal=QUIT
command = uwsgi --ini uwsgi.ini
directory = /dir/
environment=ENVIRONMENT=STAGING
logfile-maxbytes = 300MB

添加了 stopsignal=QUIT 是因为 UWSGI 忽略了停止时的默认信号 (SIGTERM),并被 SIGKILL 残忍地杀死,留下孤儿工人。

有什么方法可以调查发生的事情吗?

编辑:

按照 mnencia 的建议尝试:/etc/init.d/supervisor stop && while /etc/init.d/supervisor status ; do sleep 1; done && /etc/init.d/supervisor start 但它仍然有一半的时间失败。

 root@host:~# /etc/init.d/supervisor stop && while /etc/init.d/supervisor status ; do sleep 1; done && /etc/init.d/supervisor start
    [ ok ] Stopping supervisor (via systemctl): supervisor.service.
    ● supervisor.service - LSB: Start/stop supervisor
       Loaded: loaded (/etc/init.d/supervisor)
       Active: inactive (dead) since Tue 2015-11-24 13:04:32 UTC; 89ms ago
      Process: 23490 ExecStop=/etc/init.d/supervisor stop (code=exited, status=0/SUCCESS)
      Process: 23349 ExecStart=/etc/init.d/supervisor start (code=exited, status=0/SUCCESS)

    Nov 24 13:04:30 xxx supervisor[23349]: Starting supervisor: supervisord.
    Nov 24 13:04:30 xxx systemd[1]: Started LSB: Start/stop supervisor.
    Nov 24 13:04:32 xxx systemd[1]: Stopping LSB: Start/stop supervisor...
    Nov 24 13:04:32 xxx supervisor[23490]: Stopping supervisor: supervisord.
    Nov 24 13:04:32 xxx systemd[1]: Stopped LSB: Start/stop supervisor.
    [....] Starting supervisor (via systemctl): supervisor.serviceJob for supervisor.service failed. See 'systemctl status supervisor.service' and 'journalctl -xn' for details.
     failed!
    root@host:~# /etc/init.d/supervisor stop && while /etc/init.d/supervisor status ; do sleep 1; done && /etc/init.d/supervisor start
    [ ok ] Stopping supervisor (via systemctl): supervisor.service.
    ● supervisor.service - LSB: Start/stop supervisor
       Loaded: loaded (/etc/init.d/supervisor)
       Active: failed (Result: exit-code) since Tue 2015-11-24 13:04:32 UTC; 1s ago
      Process: 23490 ExecStop=/etc/init.d/supervisor stop (code=exited, status=0/SUCCESS)
      Process: 23526 ExecStart=/etc/init.d/supervisor start (code=exited, status=1/FAILURE)

Nov 24 13:04:32 xxx systemd[1]: supervisor.service: control process exited, code=exited status=1
Nov 24 13:04:32 xxx systemd[1]: Failed to start LSB: Start/stop supervisor.
Nov 24 13:04:32 xxx systemd[1]: Unit supervisor.service entered failed state.
Nov 24 13:04:32 xxx supervisor[23526]: Starting supervisor:
Nov 24 13:04:33 xxx systemd[1]: Stopped LSB: Start/stop supervisor.
[ ok ] Starting supervisor (via systemctl): supervisor.service.

【问题讨论】:

  • 恕我直言,您实际上遇到了一个错误。我已经就这个问题打开了debian bug
  • 我在回复中添加了解决方法
  • 谢谢,现在可以了,我接受了你的回答。

标签: debian uwsgi systemd supervisord


【解决方案1】:

这不一定是主管的错误。我从您的systemctl status 输出中看到supervisor 是通过sysv-init 兼容层启动的,因此故障可能出在/etc/init.d/supervisor 脚本中。它将解释 supervisord 日志中没有错误。

要调试 init 脚本,最简单的方法是在该文件中添加 set -x 作为第一个非注释指令,并在 journalctl 输出中查看脚本执行的跟踪。

编辑:

我已经在使用 Debian Sid 的测试系统上复制并调试了它。

问题是主管初始化脚本的 stop 目标不检查守护进程是否真的被终止,而只会在进程存在时发送信号。如果守护进程需要一段时间才能关闭,随后的 start 操作将由于正在死亡的守护进程而失败,这被视为已在运行。

我在 Debian Bug Tracker 上打开了一个错误:http://bugs.debian.org/805920

解决方法:

您可以通过以下方式解决此问题:

/etc/init.d/supervisor force-stop && \
/etc/init.d/supervisor stop && \
/etc/init.d/supervisor start
  • force-stop 将确保 supervisord 已被终止(在 systemd 之外)。
  • stop 确保 systemd 知道它已终止
  • start 又开始了

force-stop 后面的 stop 是必需的,否则 systemd 将忽略任何后续的 start 请求。 stopstart 可以使用 restart 组合在一起,但在这里我将它们都放在了这里以展示它是如何工作的。

【讨论】:

  • 这似乎可以解释正在发生的事情。正如您建议的停止实现,我可以在问题得到解决时使用“/etc/init.d/supervisor force-stop”和“/etc/init.d/supervisor start”。似乎可以接受,即使当 kill -15 不起作用时 kill -9 似乎有点矫枉过正。
  • 您可以将/etc/default/supervisor 文件中的DODTIME 常量设置为足够长的时间,以确保不会发出kill -9。默认值为 5 秒。
  • 它就像一个魅力! 10 秒似乎足以优雅地终止 100 个忙碌的工作人员。
  • 我有点太快了:force-stop->start 不启动 uwgsi,我不知道为什么,但直到我调用重启它才开始。
  • 很奇怪。也许您可以尝试使用 /etc/init.d/supervisor stop && while /etc/init.d/supervisor status ; do sleep 1; done && /etc/init.d/supervisor start 。这应该与 restart 操作所做的以及中间的更多等待没有什么不同。
【解决方案2】:

我在 ubuntu 14.04 中遇到了这个问题,尝试了来自 debian 和 @mnencia 解决方案的最新 initd 脚本,但它们对我不起作用。 force-stop 解决方案没有杀死他们只是在 supervisord 被杀死后继续运行的程序进程。

我的解决方案是修补 supervisord 并启动和重新启动部分 initd 脚本代码重试逻辑。请注意,这有点冗长,但如果您不喜欢这种行为,您可以删除 echo 调用,并且可以更改最大 reties(此处设置为 20)。

start)
    echo -n "Starting $DESC: "
    i=1
    until [ $i -ge 21 ]; do
        start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON -- $DAEMON_OPTS  && break
        echo -n -e "\nAlready running, old process still finishing? retrying ($i/20)..."
        let "i += 1"
        sleep 1
    done
sleep 1
    if running ; then
        echo "$NAME."
    else
        echo " ERROR."
    fi
;;
restart)
    echo -n "Restarting $DESC: "
    start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE
    i=1
    until [ $i -ge 21 ]; do
        start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON -- $DAEMON_OPTS  && break
        echo -n -e "\nAlready running, old process still finishing? retrying ($i/20)..."
        let "i += 1"
        sleep 1
    done
    echo "$NAME."
    ;;

我还更改了 hashbang(第一行),因此使用 bash 代替 sh,我想使用 let

#! /bin/bash

【讨论】:

    猜你喜欢
    • 2019-06-19
    • 2012-02-11
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 2013-03-21
    • 1970-01-01
    • 2011-08-17
    相关资源
    最近更新 更多