我最初是在 StackOverflow 上问这个问题的。后来我意识到这里可能是一个更好的地方。
我已设置 bluepill 来监控我的 delayed_job 进程。(Ruby On Rails 应用程序)
使用 Ubuntu 12.10。
我正在使用 Ubuntu 的 启动并监控 bluepill 服务本身upstart
。我的 upstart 配置如下 ( /etc/init/bluepill.conf
)。
description "Start up the bluepill service"
start on runlevel [2]
stop on runlevel [016]
expect daemon
exec sudo /home/deploy/.rvm/wrappers/<app_name>/bluepill load /home/deploy/websites/<app_name>/current/config/server/staging/delayed_job.bluepill
# Restart the process if it dies with a signal
# or exit code not given by the 'normal exit' stanza.
respawn
我也尝试过用expect fork
代替expect daemon
。我也尝试过expect...
完全删除该行。
当机器启动时,bluepill启动正常。
$ ps aux | grep blue
root 1154 0.6 0.8 206416 17372 ? Sl 21:19 0:00 bluepilld: <app_name>
此处 bluepill 进程的 PID 为 1154。但upstart
似乎跟踪的是错误的 PID。它跟踪的是一个不存在的 PID。
$ initctl status bluepill
bluepill start/running, process 990
sudo
我认为它正在跟踪启动 bluepill 进程的进程的 PID 。
如果我使用强制终止 bluepill,这将阻止 bluepill 进程重生kill -9
。
此外,我认为由于跟踪了错误的 PID,重启/关机就会挂起,每次我都必须硬重置机器。
这可能是什么问题?
更新:
截至今天(2015 年 5 月 3 日),Ubuntu 14.04.2 上的问题仍然存在。
问题不是因为使用 sudo。我不再使用 sudo。我更新的 upstart 配置如下:
description "Start up the bluepill service"
start on runlevel [2]
stop on runlevel [016]
# Restart the process if it dies with a signal
# or exit code not given by the 'normal exit' stanza.
respawn
# Give up if restart occurs 10 times in 90 seconds.
respawn limit 10 90
expect daemon
script
shared_path=/home/deploy/websites/some_app/shared
bluepill load $shared_path/config/delayed_job.bluepill
end script
当机器启动时,程序加载正常。但 upstart 仍然跟踪错误的 PID,如上所述。
评论中提到的解决方法可能会解决挂起问题。不过我还没有尝试过。
答案1
很晚了,但希望这可以为其他用户提供帮助。
fork
upstart 中有一个记录在案的错误,如果你在 upstart 配置中指定了不正确的节,它可能会导致 initctl 跟踪错误的 PID :https://bugs.launchpad.net/upstart/+bug/406397
实际情况是,upstart 检查fork
节并确定在选择受控程序的“真实”PID 之前应检查多少个分叉进程。如果您指定expect fork
或expect daemon
但程序分叉次数不够,start
则会挂起。另一方面,如果您的进程分叉次数过多,initctl
则会跟踪错误的 PID。理论上,应该记录在此新贵食谱的一部分但是正如您所见,在这种情况下,有一个 PID 与被终止的进程相关联,但不应该有。
这个含义在 bugtracker 评论中已经解释过了,但我将在这里总结一下:除了initctl
无法停止守护进程并陷入未记录/非法状态之外<service> start/killed, process <pid>
,如果属于该 PID 的进程停止(通常会停止),那么该 PID 将被释放以供系统重新使用。
如果您发出initctl stop <service>
或service <service> stop
,则initctl
下次出现该 PID 时,它将被终止。这意味着,如果您在犯此错误后不重新启动,则下一个使用该 PID 的进程将被立即终止,initctl
即使它不是守护进程。它可能像 一样简单,cat
也可能像 一样复杂ffmpeg
,您将很难弄清楚为什么您的软件包在某些常规操作中崩溃了。
因此,问题在于expect
您为守护进程实际进行的分叉数量指定了错误的选项。他们说有一个 upstart 重写版本可以解决这个问题,但从 upstart 1.8(最新的 Ubuntu 13.04/2014 年 1 月)开始,这个问题仍然存在。
由于您使用过expect daemon
并遇到了这个问题,我建议您尝试一下expect fork
。
编辑:这是一个与 Ubuntu BASH 兼容的脚本(原著:韦德·菲茨帕特里克修改为使用 Ubuntu sleep
)会生成进程,直到可用进程 ID 地址空间耗尽,此时它会从 0 开始,并一直运行到“卡住”的 PID。然后在initctl
挂起的 PID 处生成一个进程,并将initctl
其杀死并重置。
#!/bin/bash
# usage: sh /tmp/upstart_fix.sh <pid>
sleep 0.001 &
firstPID=$!
#first lets exhaust the space
while (( $! >= $firstPID ))
do
sleep 0.001 &
done
# [ will use testPID itself, we want to use the next pid
declare -i testPID
testPID=$(($1 - 1))
while (( $! < $testPID ))
do
sleep 0.001 &
done
# fork a background process then die so init reaps its pid
sleep 3 &
echo "Init will reap PID=$!"
kill -9 $$
# EOF
答案2
对于提供的示例:
$ initctl status bluepill
bluepill start/running, process 990
对我来说一个快速的解决方案是:
# If upstart gets stuck for some job in stop/killed state
export PID=990
cd /usr/local/bin
wget https://raw.github.com/ion1/workaround-upstart-snafu/master/workaround-upstart-snafu
chmod +x workaround-upstart-snafu
./workaround-upstart-snafu $PID
来源:https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=582745#37
我希望这会有所帮助。其他答案中解释了发生了什么。
答案3
除非你正在运行Upstart 用户级工作或者使用 setuid 节- 那么你的工作就是以 root 身份运行。
既然 Upstart 已经以 root 身份运行,为什么还需要在您的exec
节中使用 sudo?
在节中使用sudo
或给我带来了与您在此处描述的相同的问题。su
exec
通常我会经历第 1 项,或者第 1 项和第 2 项:
- upstart 遵循了错误的 PID
- 当我尝试停止该进程时,upstart 挂起了
当然,另外你还必须让expect
节反映出正确的叉数。
YMMV,但对我来说:
- 在节中使用 sudo 或 su
exec
并指定正确的 fork 数量通常会导致上述情况 1。 - 指定不正确的 fork 数量(带有或不带有 sudo/su
exec
)会导致上述情况 1 和 2。