再看stop函数的逻辑。首先使用"status"函数检查进程的状态,如果进程已在运行,则使用killproc函数杀掉它,否则表示进程未运行或进程已死,但pid文件还存在。所以,在最后删掉pidfile和lockfile。
需要注意的是,killproc杀进程时,能保证pidfile同时被删除。但它不负责lockfile,而且执行stop之前曾手动执行了"kill -9"杀进程,那么进程虽然已死,但pid文件却存在。因此也仍需手动rm删除pidfile。
killproc的调用方法为:
killproc [-p $pidfile] -[d $delay] $processname [-signal]它的逻辑和执行过程是这样的:
根据pidfile找出要杀的pid,如果没有指定pidfile,则默认从/var/run/$base.pid读取;
如果指定了要发送的信号,则killproc通过kill命令发送给定信号。0.5秒后检查/proc目录下是否还有对应目录存在,有则说明进程杀死失败,返回"[ FAILED ]"信息,否则表示成功,于是删除pid文件。
如果没有指定要发送的信号,则killproc先发送TERM信号(即kill -15),然后在给定的延迟时间delay内,每隔一秒检查一次/proc下是否有对应目录,如果发现没有,则表示进程杀死成功,于是删除pid文件(其实这种情况不用删,因为TERM信号会自动做收尾动作)。但如果delay都超时了,还发现进程存在,则发送KILL信号强制杀死进程,最后删除pid文件。
现在再理解killproc -p ${pidfile} -d ${STOP_TIMEOUT} $httpd就很简单了。
再看/etc/init.d/sshd脚本中的stop。
stop() { echo -n $"Stopping $prog: " killproc -p $PID_FILE $SSHD RETVAL=$? # if we are in halt or reboot runlevel kill all running sessions # so the TCP connections are closed cleanly if [ "x$runlevel" = x0 -o "x$runlevel" = x6 ] ; then trap '' TERM killall $prog 2>/dev/null trap TERM fi [ $RETVAL -eq 0 ] && rm -f $lockfile echo }更直接,直接就killproc。但是后面还设置了runlevel的判断情况,这就属于程序自身属性了,和服务管理脚本的逻辑框架无关。
最后再看mysqld中的stop函数。
stop(){ if [ ! -f "$mypidfile" ]; then # not running; per LSB standards this is "ok" action $"Stopping $prog: " /bin/true # pid文件都不存在,直接显示成功 return 0 fi MYSQLPID=`cat "$mypidfile" 2>/dev/null` # 读取pidfile中的pid号 if [ -n "$MYSQLPID" ]; then # 如果pid不为空,则 /bin/kill "$MYSQLPID" >/dev/null 2>&1 # 先发送默认的TERM信号杀一次 ret=$? if [ $ret -eq 0 ]; then # 如果杀成功了,则执行下面一段。 # 否则直接失败,但这不可能。为了逻辑完整,后面仍写了else TIMEOUT="$STOPTIMEOUT" while [ $TIMEOUT -gt 0 ]; do # 在延迟时间内,每隔1秒杀一次 /bin/kill -0 "$MYSQLPID" >/dev/null 2>&1 || break sleep 1 let TIMEOUT=${TIMEOUT}-1 done if [ $TIMEOUT -eq 0 ]; then # 如果达到延迟时间边界,则返回杀死进程超时信息 echo "Timeout error occurred trying to stop MySQL Daemon." ret=1 action $"Stopping $prog: " /bin/false else # 否则进程杀死成功,删除pidfile和lockfile rm -f $lockfile rm -f "$socketfile" action $"Stopping $prog: " /bin/true fi else action $"Stopping $prog: " /bin/false fi else # 如果pid为空,则表示未成功读取pidfile。 # failed to read pidfile, probably insufficient permissions action $"Stopping $prog: " /bin/false ret=4 fi return $ret }虽然有点长,但有了前面SysV脚本要具备的能力的概念,stop函数的逻辑都一样好简单。
1.5 reload函数分析关于reload函数,主要有两点:(1).语法检查;(2).发送HUP信号给"master"进程。其中语法检查要程序自身能支持,例如httpd -t,nginx -t。