如何在启动方法中启动包含无限循环的 Linux 服务(Bash 脚本)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19954067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to start a Linux service (Bash script) containing an infinite loop in the start method
提问by HRM
I'm trying to check whether one of my process is running or not every 10 minutes and if not, restart that process. I want this script to start automatically when the system boots up, so I go for services in Linux.
我正在尝试每 10 分钟检查一次我的一个进程是否正在运行,如果没有,请重新启动该进程。我希望这个脚本在系统启动时自动启动,所以我选择了Linux 中的服务。
So here is what I did:
所以这就是我所做的:
- Wrote a Bash script as a service.
- In the
start
method of the shell script, in an infinite while loop, check whether a temporary file exists. If available do my logic, else break the loop. - In the
stop
method, delete the temporary file. - Then I used update-rc.d to add this script to system boot up.
- 编写了一个 Bash 脚本作为服务。
- 在
start
shell脚本的方法中,在无限while循环中,检查临时文件是否存在。如果可用,我的逻辑,否则打破循环。 - 在该
stop
方法中,删除临时文件。 - 然后我使用 update-rc.d 将此脚本添加到系统启动中。
Everything was working fine, except one thing. If I do ./myservice start
, then the terminal hangs up (it should as it's running an infinite loop), but if I do a ctrl-z
then the script is killed and my task won't perform. How can I make this script to start from the terminal and execute normally? (like, say, ./etc/init.d/mysql start
). Maybe do the process in the background and return.
一切正常,除了一件事。如果我这样做./myservice start
,则终端挂断(它应该在无限循环中运行),但如果我这样做,ctrl-z
则脚本将被终止,我的任务将无法执行。如何让这个脚本从终端启动并正常执行?(比如,说,./etc/init.d/mysql start
)。也许在后台执行该过程并返回。
My Bash script is given below:
我的 Bash 脚本如下:
#!/bin/bash
# Start the service
start() {
#Process name that need to be monitored
process_name="mysqld"
#Restart command for process
restart_process_command="service mysql start"
#path to pgrep command
PGREP="/usr/bin/pgrep"
#Initially, on startup do create a testfile to indicate that the process
#need to be monitored. If you dont want the process to be monitored, then
#delete this file or stop this service
touch /tmp/testfile
while true;
do
if [ ! -f /tmp/testfile ]; then
break
fi
$PGREP ${process_name}
if [ $? -ne 0 ] # if <process> not running
then
# restart <process>
$restart_process_command
fi
#Change the time for monitoring process here (in secs)
sleep 1000
done
}
stop() {
echo "Stopping the service"
rm -rf /tmp/testfile
}
### main logic ###
case "" in
start)
start
;;
stop)
stop
;;
status)
;;
restart|reload|condrestart)
stop
start
;;
*)
echo $"Usage: start)
start &
{start|stop|restart|reload|status}"
exit 1
esac
exit 0
回答by devnull
Execute the function in the background. Say:
在后台执行该函数。说:
start)
start
instead of saying:
而不是说:
cat > /usr/local/bin/watch-mysql.sh <<-"__SEOF__"
#!/bin/sh
set -e
# if this file exists monitoring is stopped
if [ -f /var/run/dont-watch-mysql.lck ]; then
exit 0
fi
process_name="mysqld"
restart_process_command="service mysql restart"
PGREP="/usr/bin/pgrep"
$PGREP ${process_name}
if [ $? -ne 0 ] # if <process> not running
then
# restart <process>
$restart_process_command
fi
__SEOF__
# make the script executable
chmod u+x /usr/local/bin/watch-mysql.sh
# schedule the script to run every 10 minutes
(crontab -l ; echo "*/10 * * * * /usr/local/bin/watch-mysql.sh") | uniq - | crontab -
回答by dsumsky
In my opinion, it's worth scheduling such kind of script with cron
scheduler rather than writing standalone init script.
在我看来,值得用调度程序来调度这种脚本,cron
而不是编写独立的 init 脚本。
If you simply create the file /var/run/watch-mysql.lck
it won't be monitored.
如果您只是创建文件/var/run/watch-mysql.lck
,则不会对其进行监控。
回答by Netch
You should detach the cycle itself to a separatedscript and run the latter script from the startup one according to the manner preferred in your distribution for a non-self-daemonizing application.
您应该将循环本身分离到一个单独的脚本中,并根据非自守护应用程序的发行版中首选的方式从启动脚本运行后一个脚本。
Please notice that your current startup script will likely hang a system boot up even if not run from terminal, at least for most traditional startups (I won't say for systemd and other contemporary ones which could start multiple scripts in parallel, but they definitely will think startup isn't finished). But you could miss it if e.g. logged in via ssh because sshd will start before your script.
请注意,即使不是从终端运行,您当前的启动脚本也可能会挂起系统启动,至少对于大多数传统启动而言(我不会说 systemd 和其他可以并行启动多个脚本的当代启动脚本,但它们绝对会认为启动未完成)。但是,如果例如通过 ssh 登录,您可能会错过它,因为 sshd 将在您的脚本之前启动。