我做了一项服务叫thin_keep_alive_service
进来/etc/init.d
。我给了它chmod +x
权利。该脚本如下所示:
#!/bin/bash
### BEGIN INIT INFO
# Provides: thin_keep_alive_service
# Required-Start: $local_fs $network
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description Keeps Thin servers running
# Description: This service checks every 30 seconds if at least
# two light weight thin web servers are alive and
# restarts them all from the bundle if not.
###END INIT INFO
while true
do
# Store an array of the pids of thin
thin_pid_arr=($(pgrep -f thin))
# When there are less than two Thin servers left we reboot them all
if [ ${#thin_pid_arr[@]} -lt 2 ]; then
cd /root_to_app && bundle exec thin -C /etc/thin/app.yml restart
fi
#Wait 30 seconds before checking again
sleep 30
done
当我运行它时它确实有效service thin_keep_alive_service start
。但启动后它不会在后台持续运行,因为我的两台服务器在一段时间后就死掉了,并且没有重新启动新的服务器。
如何确保它在后台运行?
答案1
两件事情:
初始化脚本应该至少支持启动和停止命令,并且它们应该退出; initscript 中存在无限循环通常会导致引导进程在调用脚本时挂起。
我不知道
bundle exec thin restart
应该做什么,但因为否则你的脚本很好,很可能问题就在那里,即这部分没有按照你认为的那样做。您可以放入set -x
脚本以确保它在应该时运行该命令。
也就是说,如果您想要自动重新启动服务,那么使用像这样的进程管理程序几乎肯定会更干净运行。
诗。你可以通过使用while sleep 30
而不是删除 fork() while true; do ... sleep 30; done
。 :)
答案2
您可以将 Thin 安装为运行级别脚本(位于 /etc/init.d/thin 下),该脚本将在引导后启动所有服务器。
sudo thin install
并为每个要启动的应用程序设置一个配置文件:
thin config -C /etc/thin/myapp.yml -c /var/...
运行 Thin -h 以获取所有选项。
答案3
As mentioned, you should never have a loop that blocks an init script.
What I would do is create another script which is viewed as the service. That script would have the loop and it would start the service in the foreground so the loop becomes something really simple:
#!/bin/sh
while true
do
start-service ...
sleep 30
done
In your init file, you reference that script with thin or whatever other mechanism that starts a service. So you just added a layer which ensures that the service keeps running.
Now, you may also want to have a way to know when the user tries to stop the server... you do not have that in your loop either. Something like this probably:
#!/bin/sh
while true
do
start-service ...
# service properly terminated?
if ! test -f /var/run/service-id
then
exit 0
fi
sleep 30
done
If the /var/run/service-id file gets deleted before the "start-service" software returns, then you're good. It also means that if the service crashes, the file should not get deleted automatically (obviously).
Maybe you could also use the return value of the service. In that case you could do this instead (remember that works only if the service itself blocks):
#!/bin/sh
while true
do
if start-service ...
then
# service cleanly terminated
exit 0
fi
sleep 30
done
Note that this sort of a thing will auto-restart the app, but it won't do anything to force the app. to quit. If the app. does not crash but still goes bad after a while (i.e. sluggish maybe) then you'd need even more heuristic to get it to stop...
答案4
There are other ways to do this. In most common linux distributions you can use upstart
to check if a process is running and do-something if it is not. Another good option, which I'm currently using, is systemd
.
But, if you want to use third party software take a look at monit and godrb.