工作中经常需要部署一些脚本程序,这些程序很多需要运行很长时间。而有的监控脚本甚至被设计成守护进程(deamon),在服务器上每天24小时不遗余力地工作。这些程序的启动和终止就需要花一些功夫了。刚开始的手段比较原始和残暴:启动的时候往往使用nohup让其在后台静默运行;终止的时候就去进程列表里面找到进程ID然后直接kill掉。
这种方式虽然也能达到效果,但命令行操作相对较多不利于管理维护,而且不显得优雅。后来在使用其他成熟知名的应用程序,比如MySQL、Elasticsearch时,受到了启发,可以为服务写一个启动关闭程序:启动程序负责执行脚本,同时将该脚本的进程ID写入一个pid文件;关闭程序负责读取pid文件里的进程ID执行kill工作然后删除pid文件。
#!/usr/bin/env bash
# Author : 蛙鳜鸡鹳狸猿
# create_ts : 2019-10-01
# program : Start &/ stop user-defined deamon service
service="/usr/bin/env python3 monitor.py"
pid_file=monitor.pid
function start() {
# shellcheck disable=SC2154
${service} &
# shellcheck disable=SC2181
if [[ $? -eq 0 ]]; then
echo $! > ${pid_file}
else exit 1
fi
}
function stop() {
# shellcheck disable=SC2046
kill -9 $(cat ${pid_file})
# shellcheck disable=SC2181
if [[ $? -eq 0 ]]; then
rm -f ${pid_file}
else exit 1
fi
}
function call() {
case $1 in
'start')
start
;;
'stop')
stop
;;
*)
# shellcheck disable=SC2016
echo 'Get invalid option, please input(as to $1):'
echo -e '\t"start" -> start service'
echo -e '\t"stop" -> stop service'
exit 1
esac
}
call "$1"
其中“service”变量传入需要运行的脚本调用,“pid_file”定义pid文件名。示例脚本中是用Python(3)执行一个monitor的py。另外,写出被执行脚本的后台进程ID需要用到Shell中的一个特殊变量“$!”,参考https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html,https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html#Bash-Variables。
“$!”:PID of the job most recently placed into the background。
“$$”:PID of the invoking shell, not the subshell。
“$PPID”:PID of the shell’s parent process。