谷动谷力

 找回密码
 立即注册
查看: 2279|回复: 4
收起左侧

【Shell】基于 shell中stop函数分析

[复制链接]
发表于 2018-10-26 00:21:51 | 显示全部楼层 |阅读模式
【Shell】基于 shell中stop函数分析6 X. L; ^$ L3 k4 \0 b

# t8 `3 k; g9 `0 V6 U, r, J6 L, O5 S: O
仍然以/etc/init.d/httpd中的stop函数为例。( ^6 W  P( |; P0 i* ?
  1. # When stopping httpd, a delay (of default 10 second) is required& A  W( k2 E4 s3 G
  2. # before SIGKILLing the httpd parent; this gives enough time for the" \+ k. C3 V2 ?/ z5 H5 h0 ^6 H
  3. # httpd parent to SIGKILL any errant children.) y; u4 b1 @2 w5 o9 q" ]' u
  4. stop() {, |' @* r7 k) r/ @, Y
  5.      status -p ${pidfile} $httpd > /dev/null
    & A3 w9 G5 M0 I: r
  6.      if [[ $? = 0 ]]; then
    0 s; P! K' R7 U2 K. [
  7.          echo -n [        DISCUZ_CODE_0        ]quot;Stopping $prog: "
    / A) A/ O9 a8 v
  8.          killproc -p ${pidfile} -d ${STOP_TIMEOUT} $httpd
    " u  Z5 F5 S* D* w& o
  9.      else
    , ?5 J+ Q" L" o/ [2 O3 r# I
  10.          echo -n [        DISCUZ_CODE_0        ]quot;Stopping $prog: "2 l8 V' M8 i0 f4 r
  11.          success
    ! m( w- R" Q. g- f  a
  12.      fi  G: d* R4 Q9 P0 H6 D
  13.      RETVAL=$?
    & [0 w0 {* g' u3 i& h1 }
  14.      echo
      [* r# y% L. E" n* ~
  15.      [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}1 U6 _" N  n! ?8 s, }
  16. }
复制代码
) D/ v0 c5 W/ M2 P& b& E! r7 E7 s
4 Z$ _- [) m% S6 U3 f- y
前面加了一段注释,大致意思是说这里杀死进程的行为和httpd自带的apachectl工具停止服务的命令"apachectl -k stop"的行为是不同的。之所以我要把这一段也贴上来,也就是为了说明这一点。有些服务程序自带进程管理工具,亦或是使用functions中的函数,完全由我们自己决定。% E* A* J: n- c; V, E3 _9 N( k

' h6 B% ?* @- M$ K 再看stop函数的逻辑。首先使用"status"函数检查进程的状态,如果进程已在运行,则使用killproc函数杀掉它,否则表示进程未运行或进程已死,但pid文件还存在。所以,在最后删掉pidfile和lockfile。
& D0 K% U3 ?- p- H
6 _0 H, t5 M5 e, X/ G 需要注意的是,killproc杀进程时,能保证pidfile同时被删除。但它不负责lockfile,而且执行stop之前曾手动执行了"kill -9"杀进程,那么进程虽然已死,但pid文件却存在。因此也仍需手动rm删除pidfile。
* p0 t' r  m+ g+ m7 D1 I
7 m7 O3 D2 N8 skillproc的调用方法为:
8 a$ v* ?  N3 q
  1. killproc [-p $pidfile] -[d $delay] $processname [-signal]
复制代码
/ ^# p: d3 a# L- m
它的逻辑和执行过程是这样的:
/ j( ?" l/ I' R7 l: |$ j; ]( u3 D, d# u
根据pidfile找出要杀的pid,如果没有指定pidfile,则默认从/var/run/$base.pid读取;) m( r& B6 G! i" p
如果指定了要发送的信号,则killproc通过kill命令发送给定信号。0.5秒后检查/proc目录下是否还有对应目录存在,有则说明进程杀死失败,返回"[ FAILED ]"信息,否则表示成功,于是删除pid文件。0 V) h5 |4 h) @' A- s; W* M
如果没有指定要发送的信号,则killproc先发送TERM信号(即kill -15),然后在给定的延迟时间delay内,每隔一秒检查一次/proc下是否有对应目录,如果发现没有,则表示进程杀死成功,于是删除pid文件(其实这种情况不用删,因为TERM信号会自动做收尾动作)。但如果delay都超时了,还发现进程存在,则发送KILL信号强制杀死进程,最后删除pid文件。
" a0 d/ @4 G% x( k6 a1 t! q 现在再理解killproc -p ${pidfile} -d ${STOP_TIMEOUT} $httpd就很简单了。$ w9 s7 u. Q( u; m0 u$ w# o
1 H+ q- P' d- i+ A- p  E5 k
再看/etc/init.d/sshd脚本中的stop。( h( J9 ~- s4 B' r4 x  i. ?

7 U+ c: o- L4 H1 a+ v
  1. stop()
    2 V5 I$ \6 y( }* N* Q6 j
  2. {; c$ N1 z& t% C8 S9 Q- q5 `8 Z
  3.      echo -n [        DISCUZ_CODE_2        ]quot;Stopping $prog: "
    1 y' N  V5 G; K+ U
  4.      killproc -p $PID_FILE $SSHD
    & p) W5 u( ?. B" P/ t
  5.      RETVAL=$?
    5 c% a4 z* f9 m5 |" K
  6.      # if we are in halt or reboot runlevel kill all running sessions
    - s1 `! @, j6 G+ ?* R; r! z* J
  7.      # so the TCP connections are closed cleanly1 \: L0 m) T' z' o! P0 N1 \
  8.      if [ "x$runlevel" = x0 -o "x$runlevel" = x6 ] ; then. k( P0 I3 \/ e: i  x" D+ f
  9.          trap '' TERM
    " k1 f  |; R3 J
  10.          killall $prog 2>/dev/null2 [1 V, G$ u: c% e
  11.          trap TERM
    ) A4 H; L, {+ f) `+ `) s) t, Z6 p
  12.      fi
    6 T4 Q1 o) v' t8 X  G% G/ l1 W
  13.      [ $RETVAL -eq 0 ] && rm -f $lockfile
    . G+ Z+ I, }0 _) F
  14.      echo2 O# k' @) {' X7 P( f9 j0 p+ o
  15. }
复制代码
' m! k' ^2 i$ M# a1 M: o+ A$ q* u
更直接,直接就killproc。但是后面还设置了runlevel的判断情况,这就属于程序自身属性了,和服务管理脚本的逻辑框架无关。$ s% a% I3 p2 Y% A

, o- V" K+ U' z& b/ E, u4 B, b& a 最后再看mysqld中的stop函数。1 ]9 T- n+ Y' O+ z6 Y0 b
  1. stop(){
    8 N* u6 S- j9 G8 u$ f1 x
  2.      if [ ! -f "$mypidfile" ]; then
    * i! T) F9 {8 g( b5 E7 I4 g
  3.          # not running; per LSB standards this is "ok"
    # H9 ?. w1 _  a
  4.          action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/true      # pid文件都不存在,直接显示成功$ X) V1 \8 }9 A# T* P, N
  5.         return 0
    + C# D) u- ^0 c5 I" |* q, e
  6.      fi
    9 \' [( s  L6 k5 J2 B; k8 o) v
  7.      MYSQLPID=`cat "$mypidfile" 2>/dev/null`       # 读取pidfile中的pid号) U# v$ \" q. [
  8.     if [ -n "$MYSQLPID" ]; then                   # 如果pid不为空,则8 }" z5 q& E" [
  9.         /bin/kill "$MYSQLPID" >/dev/null 2>&1     # 先发送默认的TERM信号杀一次* @) @5 j. q$ p' j" O
  10.         ret=$?
    , \6 m' S5 M- l0 z
  11.          if [ $ret -eq 0 ]; then         # 如果杀成功了,则执行下面一段。7 q3 k" Y) H5 F% t4 w' P  K
  12.                                         # 否则直接失败,但这不可能。为了逻辑完整,后面仍写了else& w  i( g# N* G
  13.              TIMEOUT="$STOPTIMEOUT"' T6 b) _% O" G) W+ w
  14.              while [ $TIMEOUT -gt 0 ]; do   # 在延迟时间内,每隔1秒杀一次) n' |6 n0 w# N
  15.                 /bin/kill -0 "$MYSQLPID" >/dev/null 2>&1 || break: b9 c' \# Q' U; g1 j
  16.                  sleep 1
    9 ]$ u7 c( P" m" T! Q# D
  17.                  let TIMEOUT=${TIMEOUT}-1  ?- U6 c: N7 o% N
  18.              done6 R* a# F: _/ w2 n% y2 g4 e
  19.              if [ $TIMEOUT -eq 0 ]; then    # 如果达到延迟时间边界,则返回杀死进程超时信息
    9 ~( V# Q$ S. }7 q. m
  20.                 echo "Timeout error occurred trying to stop MySQL Daemon."
      U9 g9 s1 _( s, J
  21.                  ret=1
    , q3 A% {% v, S8 {9 x' Q
  22.                  action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/false
    " |& S" V' _  ]# }
  23.              else                           # 否则进程杀死成功,删除pidfile和lockfile
    9 ?% }# m- ^0 e7 X
  24.                  rm -f $lockfile
    + O" H: G) r. V  p/ ]$ x) l2 z+ |& g
  25.                  rm -f "$socketfile"( _' D3 a+ t9 r+ I
  26.                  action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/true$ c" b& P0 [4 b
  27.              fi8 W( B: `$ z1 {8 L
  28.          else. S* Q( ?3 w- h8 J6 a1 c/ g
  29.              action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/false
    / f& i* T4 }: S, r6 g4 {" ?& T" K
  30.          fi. f, @# q8 ]) u% f, @, F) x
  31.      else                                   # 如果pid为空,则表示未成功读取pidfile。
    6 q7 U0 @2 Q2 I8 A5 b0 {% }. |
  32.         # failed to read pidfile, probably insufficient permissions
    / [0 w: T4 E. N. q$ _' m
  33.          action [        DISCUZ_CODE_3        ]quot;Stopping $prog: " /bin/false: j" Q, v8 @; O2 H! g' i7 _
  34.          ret=4# n( F* c8 [. G) b
  35.      fi# H- G! f: V" q8 \% |2 J9 F, v$ D
  36.      return $ret( k9 Z6 d- a! t1 m8 Q* Z& Y
  37. }
复制代码

7 l6 v9 M& G, I/ U6 w3 n3 e' a基于 shell中stop函数分析
- T( U4 m6 _! D; |1 Bhttp://bbs.cirmall.com/thread-52158-1-1.html, R7 u: _9 A( o$ i- l+ m, e1 @
(出处: 电路城)
# |# o: C9 b1 O6 O4 M. {

本帖被以下淘专辑推荐:

  • · Shell|主题: 28, 订阅: 0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|深圳市光明谷科技有限公司|光明谷商城|Sunshine Silicon Corpporation ( 粤ICP备14060730号|Sitemap

GMT+8, 2024-3-29 03:14 , Processed in 0.081269 second(s), 33 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表