谷动谷力

标题: 【Shell】基于 shell中stop函数分析 [打印本页]

作者: sunsili    时间: 2018-10-26 00:21
标题: 【Shell】基于 shell中stop函数分析
【Shell】基于 shell中stop函数分析


仍然以/etc/init.d/httpd中的stop函数为例。
  1. # When stopping httpd, a delay (of default 10 second) is required
  2. # before SIGKILLing the httpd parent; this gives enough time for the
  3. # httpd parent to SIGKILL any errant children.
  4. stop() {
  5.      status -p ${pidfile} $httpd > /dev/null
  6.      if [[ $? = 0 ]]; then
  7.          echo -n [        DISCUZ_CODE_0        ]quot;Stopping $prog: "
  8.          killproc -p ${pidfile} -d ${STOP_TIMEOUT} $httpd
  9.      else
  10.          echo -n [        DISCUZ_CODE_0        ]quot;Stopping $prog: "
  11.          success
  12.      fi
  13.      RETVAL=$?
  14.      echo
  15.      [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
  16. }
复制代码


前面加了一段注释,大致意思是说这里杀死进程的行为和httpd自带的apachectl工具停止服务的命令"apachectl -k stop"的行为是不同的。之所以我要把这一段也贴上来,也就是为了说明这一点。有些服务程序自带进程管理工具,亦或是使用functions中的函数,完全由我们自己决定。

再看stop函数的逻辑。首先使用"status"函数检查进程的状态,如果进程已在运行,则使用killproc函数杀掉它,否则表示进程未运行或进程已死,但pid文件还存在。所以,在最后删掉pidfile和lockfile。

需要注意的是,killproc杀进程时,能保证pidfile同时被删除。但它不负责lockfile,而且执行stop之前曾手动执行了"kill -9"杀进程,那么进程虽然已死,但pid文件却存在。因此也仍需手动rm删除pidfile。

killproc的调用方法为:
  1. 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。

  1. stop()
  2. {
  3.      echo -n [        DISCUZ_CODE_2        ]quot;Stopping $prog: "
  4.      killproc -p $PID_FILE $SSHD
  5.      RETVAL=$?
  6.      # if we are in halt or reboot runlevel kill all running sessions
  7.      # so the TCP connections are closed cleanly
  8.      if [ "x$runlevel" = x0 -o "x$runlevel" = x6 ] ; then
  9.          trap '' TERM
  10.          killall $prog 2>/dev/null
  11.          trap TERM
  12.      fi
  13.      [ $RETVAL -eq 0 ] && rm -f $lockfile
  14.      echo
  15. }
复制代码

更直接,直接就killproc。但是后面还设置了runlevel的判断情况,这就属于程序自身属性了,和服务管理脚本的逻辑框架无关。

最后再看mysqld中的stop函数。
  1. stop(){
  2.      if [ ! -f "$mypidfile" ]; then
  3.          # not running; per LSB standards this is "ok"
  4.          action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/true      # pid文件都不存在,直接显示成功
  5.         return 0
  6.      fi
  7.      MYSQLPID=`cat "$mypidfile" 2>/dev/null`       # 读取pidfile中的pid号
  8.     if [ -n "$MYSQLPID" ]; then                   # 如果pid不为空,则
  9.         /bin/kill "$MYSQLPID" >/dev/null 2>&1     # 先发送默认的TERM信号杀一次
  10.         ret=$?
  11.          if [ $ret -eq 0 ]; then         # 如果杀成功了,则执行下面一段。
  12.                                         # 否则直接失败,但这不可能。为了逻辑完整,后面仍写了else
  13.              TIMEOUT="$STOPTIMEOUT"
  14.              while [ $TIMEOUT -gt 0 ]; do   # 在延迟时间内,每隔1秒杀一次
  15.                 /bin/kill -0 "$MYSQLPID" >/dev/null 2>&1 || break
  16.                  sleep 1
  17.                  let TIMEOUT=${TIMEOUT}-1
  18.              done
  19.              if [ $TIMEOUT -eq 0 ]; then    # 如果达到延迟时间边界,则返回杀死进程超时信息
  20.                 echo "Timeout error occurred trying to stop MySQL Daemon."
  21.                  ret=1
  22.                  action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/false
  23.              else                           # 否则进程杀死成功,删除pidfile和lockfile
  24.                  rm -f $lockfile
  25.                  rm -f "$socketfile"
  26.                  action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/true
  27.              fi
  28.          else
  29.              action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/false
  30.          fi
  31.      else                                   # 如果pid为空,则表示未成功读取pidfile。
  32.         # failed to read pidfile, probably insufficient permissions
  33.          action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/false
  34.          ret=4
  35.      fi
  36.      return $ret
  37. }
复制代码

基于 shell中stop函数分析
http://bbs.cirmall.com/thread-52158-1-1.html
(出处: 电路城)





欢迎光临 谷动谷力 (http://bbs.sunsili.com/) Powered by Discuz! X3.2