新贵跟踪错误的过程PID – 而不是重生
我最初在StackOverflow上问过这个问题。 然后意识到这可能是一个更好的地方。
我有bluepill设置来监控我的delayed_job进程。 (Ruby On Rails应用程序)
使用Ubuntu 12.10。
我正在使用Ubuntu的upstart
启动并监控bluepill服务。 我的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//bluepill load /home/deploy/websites//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:
bluepill过程的PID在这里是1154。 但upstart
似乎正在跟踪错误的PID。 它正在跟踪一个不存在的PID。
$ initctl status bluepill bluepill start/running, process 990
我认为它正在跟踪启动bluepill流程的sudo
进程的PID。
如果我使用kill -9
强行杀死bluepill,这会阻止bluepill进程重生。
此外,我认为由于跟踪错误的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
当机器启动时,程序加载正常。 但如上所述,暴发户仍会追踪错误的PID。
评论中提到的解决方法可能会解决悬而未决的问题。 不过我还没试过。
很晚,但希望这对其他用户有帮助。
如果在upstart配置中指定了错误的fork
节,那么upstart中存在一个记录错误,可能导致initctl跟踪错误的PID: https : //bugs.launchpad.net/upstart/+bug/406397
发生的事情是upstart检查fork
节并确定在选择被控制程序的“true”PID之前应该检查多少分叉进程。 如果指定expect fork
或expect daemon
但程序没有分叉足够多次,则start
将挂起。 另一方面,如果您的进程分叉太多次, initctl
将跟踪错误的PID。 从理论上讲,它应该记录在新手本食谱的这一部分中 ,但正如你在这种情况下所看到的那样,当不存在时,会有一个与被杀死进程相关的PID。
在bugtracker评论中解释了这一点的含义,但我将在此总结:除了initctl
无法停止守护进程并陷入无证/非法状态
,如果属于该PID的进程停止(通常会),然后释放PID以供系统重用。
如果发出initctl stop
或service
, initctl
将在下次出现时service
该PID。 这意味着,如果你在犯这个错误后没有重新启动,那么下一个使用该PID的进程将立即被initctl
杀死,即使它不是守护进程。 它可能像cat
一样简单,也可能像ffmpeg
一样复杂,而且你很难弄清楚为什么你的软件包在一些例行操作中崩溃了。
因此,问题在于您为守护程序进程实际生成的分叉数指定了错误的expect
选项。 他们说有一个新贵重写可以解决这个问题,但截至新贵1.8(最新的Ubuntu 13.04 / 2014年1月),问题仍然存在。
由于您使用了expect daemon
并最终遇到此问题,我建议您尝试使用expect fork
。
编辑:这是一个与Ubuntu BASH兼容的脚本( 原来由Wade Fitzpatrick修改为使用Ubuntu sleep
),它产生进程直到可用的进程ID地址空间耗尽,此时它从0开始并一直向上运行到“卡住” “PID。 然后在PID initctl
挂起的过程中生成一个进程, initctl
其initctl
并重置。
#!/bin/bash # usage: sh /tmp/upstart_fix.sh 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
对于提供的示例:
$ 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?bad = 582745#37
我希望这会有所帮助。 在其他答案中解释了正在发生的事情。
除非您正在运行Upstart用户级作业或使用setuid节 – 否则您的作业将以root身份运行。
由于Upstart已经以root身份运行,为什么你需要在你的exec
节中使用sudo?
在exec
节中使用sudo
或su
给我带来了同样的问题,就像你在这里描述的那样。
通常我会遇到第1项或1和2:
- upstart跟随不正确的PID
- 当我试图阻止这个过程时,暴发户就会挂起
当然,另外你必须有expect
节反映正确的叉子数量。
YMMV,但对我来说:
- 在
exec
节中使用sudo或su并指定正确数量的货叉通常会导致上述情况1。 - 指定的分叉数量不正确(我们在
exec
没有sudo / su)导致上面的情况1和2。