我编写了一个 upstart 脚本来在 tmux 会话中启动守护进程。它运行良好,如果进程意外终止,它会重新启动,但我似乎无法手动停止它。
这个作业(称为 bukkit)如下所示:
start on filesystem
stop on runlevel [!2345]
respawn
respawn limit 5 30
chdir /home/minecraft/bukkit
expect daemon
kill timeout 30
pre-start script
test -x /home/minecraft/bukkit/craftbukkit-0.0.1-SNAPSHOT.jar || { stop; exit 0; }
end script
pre-stop script
tmux send -t bukkit "stop"
tmux send -t bukkit "Enter"
sleep 10 # Wait for server to shut down properly
end script
exec tmux new-session -d -s minecraft -n bukkit "sudo -u minecraft -- /home/minecraft/java/jre1.6.0_27/bin/java -Xincgc -Xmx1G -jar /home/minecraft/bukkit/craftbukkit-0.0.1-SNAPSHOT.jar"
当我发出一个命令时,stop bukkit
它会冻结约 10 秒(我猜是睡眠定时器)并打印bukkit start/running, process 2391
。当我设置 upstart 进行调试时,我在日志中发现了以下相关行:
Sep 21 19:14:59 cheftest init: bukkit goal changed from start to stop
Sep 21 19:14:59 cheftest init: bukkit main process (2499) exited normally
Sep 21 19:14:59 cheftest init: bukkit main process ended, respawning
Sep 21 19:14:59 cheftest init: bukkit goal changed from stop to respawn
为什么当 upstart 应该停止我的进程时它却不断重新启动它?
答案1
这里的难点在于“respawn”与停止前脚本的结合,该脚本指示进程停止。从 init(5) 开始:
respawn A service or task with this stanza will be automatically started if it should stop abnormally. All reasons for a service stopping, except the stop(8) command itself, are considered abnormal. Tasks may exit with a zero exit status to prevent being respawned.
文档对于以零退出状态退出是否会导致重生的问题有些不清楚。但是,从根本上讲,您发现了一个 upstart 错误,因为当目标是“停止”时,主进程的结束不应该导致更改为“重生”。
为了解决此错误,您应该能够使用“正常退出”来告诉 upstart,这是停止作业的正常方式,并且它不应该重新启动。
normal exit STATUS|SIGNAL... Additional exit statuses or even signals may be added, if the job process terminates with any of these it will not be considered to have failed and will not be respawned. normal exit 0 1 TERM HUP
请注意,一般来说,使用信号(必要时指定“kill signal N”)来终止进程比使用发出命令的预停止进程更为可靠;但是,如果服务不支持在收到信号后干净关闭,这当然并不总是可行的。
答案2
以防其他人也遇到这种情况,我已经提交了一个可以修复这个漏洞的补丁:
答案3
upstart 1.10 中已经发布了针对此问题的修复程序,因此现在不会再发生这种情况。