新贵跟踪错误的过程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 forkexpect daemon但程序没有分叉足够多次,则start将挂起。 另一方面,如果您的进程分叉太多次, initctl将跟踪错误的PID。 从理论上讲,它应该记录在新手本食谱的这一部分中 ,但正如你在这种情况下所看到的那样,当不存在时,会有一个与被杀死进程相关的PID。

在bugtracker评论中解释了这一点的含义,但我将在此总结:除了initctl无法停止守护进程并陷入无证/非法状态 start/killed, process ,如果属于该PID的进程停止(通常会),然后释放PID以供系统重用。

如果发出initctl stop service stopinitctl将在下次出现时service stop该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挂起的过程中生成一个进程, initctlinitctl并重置。

 #!/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节中使用sudosu给我带来了同样的问题,就像你在这里描述的那样。

通常我会遇到第1项或1和2:

  1. upstart跟随不正确的PID
  2. 当我试图阻止这个过程时,暴发户就会挂起

当然,另外你必须有expect节反映正确的叉子数量。

YMMV,但对我来说:

  • exec节中使用sudo或su并指定正确数量的货叉通常会导致上述情况1。
  • 指定的分叉数量不正确(我们在exec没有sudo / su)导致上面的情况1和2。