为什么新贵不断重生我的进程?

pas*_*ssy 19 server upstart tmux

我编写了一个新贵脚本来在 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"
Run Code Online (Sandbox Code Playgroud)

当我发出 a 时,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
Run Code Online (Sandbox Code Playgroud)

为什么暴发户在应该停止它时会继续重生我的进程?

sla*_*sek 23

这里的困难在于将“重生”与告诉进程停止的预停止脚本相结合。从 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.
Run Code Online (Sandbox Code Playgroud)

关于以零退出状态退出是否应该导致重生,文档有点不清楚。但是,从根本上说,您发现了一个新贵错误,因为当目标为“停止”时结束的主进程不应导致“重生”的更改。

要解决此错误,您应该能够使用“正常退出”来告诉暴发户这是停止作业的正常方式,并且不应重新生成。

  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
Run Code Online (Sandbox Code Playgroud)

请注意,一般而言,使用信号终止进程(如果需要,指定“终止信号 N”)而不是使用发出命令的预停止进程会更健壮;但当然,如果服务在收到信号时不支持干净关闭,这并不总是可行的。