Chinaunix首页 | 论坛 | 博客
  • 博客访问: 135170
  • 博文数量: 28
  • 博客积分: 527
  • 博客等级: 中士
  • 技术积分: 367
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-09 17:05
个人简介

运维开发工程师。致力于网络,WEB应用服务,Linux系统运维。方向:操作系统,监控,自动化

文章分类

全部博文(28)

文章存档

2013年(12)

2012年(16)

分类: LINUX

2012-11-20 10:08:52

问题
tomcat是一款非常实用强大的servlet container。但其停止过程一直让人困扰。由于$CATALINA_HOME/bin下的shutdown.sh必须等待所有处理线程退出才会生效,等待时间不可控,因此单靠shutdown.sh不能十分理想地关闭服务(至少在一段时间内不理想)。使得运维人员不得不频繁kill ps查看,造成重复操作。
我参考了startup.sh和shutdown.sh的写法,封装了下catalina.sh。

解决思路
简单谈谈解决思路,主要实现集中在关闭服务功能。shutdown_Tomcat函数首先调用catalina自带的shutdown.sh关闭服务,若返回失败,依次调用kill_Tomcat和Force_Tomcat函数。这两个函数内循环kill5次,每次间隔5s并检测存活与否,若是则返回0码。start_Tomcat先检测了当前tomcat实例,避免重复启动。

调用方法
  1. cd $CATALINA_HOME/bin && sh tomcat_control.sh start
  2. #cd $CATALINA_HOME/bin 不可省略

限制
  1. 设定的是通过当前pwd来定位tomcat进程,因此一个启停脚本对应一个tomcat实例,且须放置在$CATALINA/bin下,也就是和catalina.sh同目录
  2. 使用tomcat_control.sh时,要先cd到$CATALINA_HOME下

技术点
  1. heredoc实现多行注释;
  2. set -u 防止使用未赋值的变量;set -o pipefail 检测并返回管道内部错误,而非默认的管道最后一个命令返回值
  3. 判断进程是否存在的几个方法:kill -0 $pid 或 cat /proc/$pid/cmdline,不推荐用ps aux|grep $pid的做法
  4. 远程调用bugfix:ssh user@host "cd $CATALINA_HOME/bin && sh tomcat_control.sh start"时,ps会额外返回记录:"bash -c cd $CATALINA_HOME/bin && sh tomcat_control.sh start",脚本内额外grep -v "$0"做了处理

环境
apache-tomcat-5.5.36
linux 2.6.9

实现
  1. #!/bin/bash
  2. set -o pipefail
  3. set -u
  4. #环境设置
  5. TOMCAT_BIN=`pwd`
  6. TOMCAT_EXEC=$TOMCAT_BIN/catalina.sh

  7. #时间设置
  8. START_WAIT=5
  9. SHUT_WAIT=10
  10. KILL_INTERVAL=5
  11. KILL_TIMES=5

  12. #返回码设置
  13. RET_SUCCESS=0
  14. RET_TOMCAT_DEAD=1
  15. RET_ERROR_SHUT=2
  16. RET_ERROR_START=3

  17. #获取当前tomcat实例pid
  18. PID=`ps -ef | grep -vE "grep $TOMCAT_BIN|$0" | grep $TOMCAT_BIN | awk '{print $2}'`

  19. function usage(){
  20. :<< \# 用heredoc实现多行注释
  21. Purpose : This script encapsulates the catalina.sh and take care of the start/stop/restart process of tomcat, and just acts like a tomcat controller.
  22. Usage : sh tomcat_control start|stop|restart
  23. Date : 2012.11
  24. #
  25. }

  26. #检测tomcat:$pid是否存活
  27. function is_Tomcat_Alive(){
  28. #kill -0 : test process alived or not
  29. if `kill -0 $PID 2>/dev/null` ; then
  30. #0 stands for success in shell
  31. return $RET_SUCCESS
  32. else
  33. return $RET_TOMCAT_DEAD
  34. fi
  35. }
  36. function shutdown_Tomcat(){
  37. if is_Tomcat_Alive ; then
  38. echo -n "stopping $PID "
  39. sh $TOMCAT_EXEC stop 1>/dev/null 2>&1
  40. sleep_Wait $SHUT_WAIT
  41. if is_Tomcat_Alive ; then
  42. #if normally shutdown does not take effect in $KILL_WAIT secs
  43. return $RET_ERROR_SHUT
  44. else
  45. #if shutdown works well
  46. echo shutdown successfully
  47. return $RET_SUCCESS
  48. fi
  49. else
  50. echo "no need to shut"
  51. return $RET_SUCCESS
  52. fi
  53. }
  54. #正常kill
  55. function kill_Tomcat(){
  56. echo -n "killing $PID "
  57. for((i=0;i<=$KILL_TIMES;i ));do #kill tomcat for KILL_TIMES, each with KILL_INTERVAL secs
  58. kill $PID
  59. sleep_Wait $KILL_INTERVAL
  60. #check if kill of this round success
  61. if ! is_Tomcat_Alive ; then
  62. echo shutdown successfully
  63. return $RET_SUCCESS
  64. fi
  65. done
  66. return $RET_ERROR_SHUT
  67. }
  68. #-9 kill
  69. function force_Tomcat(){
  70. echo -n "force killing $PID "
  71. for((i=0;i<=$KILL_TIMES;i ));do
  72. #kill tomcat for KILL_TIMES, each with KILL_INTERVAL secs
  73. kill -9 $pid
  74. sleep_Wait $KILL_INTERVAL
  75. if ! is_Tomcat_Alive ; then
  76. echo shutdown successfully #check if force kill of this round success
  77. return $RET_SUCCESS
  78. fi
  79. done
  80. #now if pid still exists
  81. echo shutdown failed, pls manually check
  82. return $RET_ERROR_SHUT
  83. }
  84. #等待时间,加动画
  85. function sleep_Wait(){
  86. local sec=$1
  87. for((i=1;i<=$sec;i ));do
  88. sleep 1
  89. echo -n "."
  90. done
  91. echo
  92. }

  93. #启动
  94. function startup_Tomcat(){
  95. ##This function enables the tomcat
  96. if is_Tomcat_Alive; then
  97. #ps -ef|grep $PID
  98. echo no need to start, tomcat pid : $PID, exit
  99. else
  100. echo -n "starting "
  101. sh $TOMCAT_EXEC start 1>/dev/null 2>&1
  102. sleep_Wait $START_WAIT
  103. local pid=`ps -ef | grep -vE "grep $TOMCAT_BIN|$0" | grep $TOMCAT_BIN | awk '{print $2}'`
  104. #do not if [ `some cmd` ]
  105. if `grep -q $TOMCAT_BIN /proc/$pid/cmdline` ; then
  106. echo start successfully : $pid
  107. return $RET_SUCCESS
  108. else
  109. echo start failed
  110. return $RET_ERROR_START
  111. fi
  112. fi
  113. }
  114. #调度器
  115. function dispatcher(){
  116. local args=$1
  117. case "$args" in
  118. stop)
  119. shutdown_Tomcat || kill_Tomcat || force_Tomcat
  120. ;;
  121. kill)
  122. kill_Tomcat || force_Tomcat
  123. ;;
  124. force)
  125. force_Tomcat
  126. ;;
  127. start)
  128. startup_Tomcat
  129. ;;
  130. restart)
  131. shutdown_Tomcat || kill_Tomcat || force_Tomcat && startup_Tomcat
  132. ;;
  133. *)
  134. usage
  135. ;;
  136. esac
  137. }
  138. dispatcher "$@"
  139. #END
验证
在生产环境中实测通过,小概率存在函数级联调用执行间隙,$pid已被kill而又被下一级函数复杀的问题,忽略即可。
阅读(2653) | 评论(0) | 转发(0) |
0

上一篇:014-sed

下一篇:perl--grep列表操作符

给主人留下些什么吧!~~