方法一:html
查找tomcat進程並killjava
ps -elf | grep ${ctompath} | grep -v grep | awk '{print $4}' | xargs kill -9apache
此處可寫成腳本,可參考我以前的腳本 https://www.cnblogs.com/shenjianxin/p/9263765.htmlbootstrap
方法二:tomcat
修改$TOMCAT_HOME/bin/catalina.sh文件,在PRGDIR下面一行添加CATALINA_PID參數行,修改完成後應該跟下面相同。socket
# Get standard environment variables PRGDIR=`dirname "$PRG"` CATALINA_PID=$PRGDIR/CATALINA_PID源碼分析
也能夠自定義pid路徑,例如「CATALINA_PID=/var/run/tomcat.pid」測試
要殺死進程須要添加參數 -force ./shutdown.sh -force 或者 ./catalina.sh stop -forceui
源碼分析:(如下出處https://blog.csdn.net/hxyerui/article/details/52181884)spa
最近咱們在使用Jenkins自動化部署項目時,在生產liunx環境下,使用腳本shutdown.sh中止tomcat服務,而後再start以後發現應用沒法訪問了,後臺查看tomcat進程是發現有個2個tomcat進程,說明以前的shutdown並無徹底停掉tomcat進程。那怎麼樣tomcat使用shutdown以後立馬關掉其進程呢? 經查資料發如今shutdown.sh腳本以後有條命令是這樣的:
exec "$PRGDIR"/"$EXECUTABLE" stop "$@"
這個就是中止tomcat 服務的命令,咱們只須要加一個 -force 就能夠在shutdown時強制關閉tomcat進程
exec "$PRGDIR"/"$EXECUTABLE" stop -force "$@"
但光這樣仍是不行,再shutdown時報錯:
Kill failed: $CATALINA_PID not set
查找失敗緣由:
從中能夠看到,首先是執行java命令失敗,沒有中止tomcat,而後執行-force模塊的命令,可是卻沒有找到$CATALINA_PID設定的進程號,咱們先不去關注java執行stop命令爲何報錯,而是看看爲何加了-force參數也不起做用了
爲何沒有$CATALINA_PID?接下來就帶你們一探究竟
首先,咱們將涉及到$CATALINA_PID變量的代碼所有提取出來:
第一處:
#如下這句判斷設置的$CATALINA_PID變量若是不存在,則顯示"Using CATALINA_PID:
#貌似只是判斷$CATALINA_PID是不是空字符,其餘什麼都沒有作
第二處:(涉及到start參數的模塊內的$CATALINA_PID變量,只是提出來分析,其實不對stop模塊有影響)
#這個是start模塊內的代碼 "$_RUNJAVA" "$LOGGING_CONFIG" $JAVA_OPTS $CATALINA_OPTS \ -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \ -Dcatalina.base="$CATALINA_BASE" \ -Dcatalina.home="$CATALINA_HOME" \ -Djava.io.tmpdir="$CATALINA_TMPDIR" \ org.apache.catalina.startup.Bootstrap "$@" start \ >> "$CATALINA_OUT" 2>&1 & #從&能夠看出啓動的命令在後臺啓動 fi if [ ! -z "$CATALINA_PID" ]; then #判斷CATALINA_PID若是不是空字符,則將Shell最後運行的後臺Process的PID 傳給$CATALINA_PID echo $! > "$CATALINA_PID" #在使用命令運行進程至後臺時,可使用$!抓取前面啓動運行在後臺進程的進程號 fi fi #上面語句是tomcat在啓動時,會將$CATALINA_PID寫入PID進程號
第三處:
#一下語句都出如今stop模塊內 if [ ! -z "$CATALINA_PID" ]; then #$CATALINA_PID文件不是非空 if [ -f "$CATALINA_PID" ]; then if [ -s "$CATALINA_PID" ]; then kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1 #kill -0 pid 不發送任何信號,可是系統會進行錯誤檢查。 if [ $? -gt 0 ]; then echo "PID file found but no matching process was found. Stop aborted." exit 1 fi else echo "PID file is empty and has been ignored." fi else echo "\$CATALINA_PID was set but the specified file does not exist. Is Tomcat running? Stop aborted." exit 1 fi fi
#若是發現$CATALINA_PID則發送一個模擬結束進程的型號,若是返回值爲0,則正常,其餘則異常,作退出操做
#從上面的sh -x輸出的信息對應的是:'[' '!' -z '' ']' 能夠看出$CATALINA_PID變量沒有設定,因此這個判斷直接就結束了,什麼都沒作
第四處:
#下面的代碼緊接着stop的正常中止代碼下 if [ ! -z "$CATALINA_PID" ]; then #若是$CATALINA_PID不爲空 if [ -f "$CATALINA_PID" ]; then #並且仍是普通文件 while [ $SLEEP -ge 0 ]; do #並且$SLEEP還大於0 kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1 #則測試下tomcat能不能被關閉 if [ $? -gt 0 ]; then #剩下的參數還有,則清空$CATALINA_PID rm -f "$CATALINA_PID" >/dev/null 2>&1 if [ $? != 0 ]; then if [ -w "$CATALINA_PID" ]; then cat /dev/null > "$CATALINA_PID" else echo "Tomcat stopped but the PID file could not be removed or cleared." fi fi break fi if [ $SLEEP -gt 0 ]; then sleep 1 fi if [ $SLEEP -eq 0 ]; then if [ $FORCE -eq 0 ]; then echo "Tomcat did not stop in time. PID file was not removed." fi fi SLEEP=`expr $SLEEP - 1 ` done fi fi #上段語句主要是判斷tomcat是否被關閉 #核心語句仍是:kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1 #while語句作sleep使用,用於清空$CATALINA_PID #可是[ ! -z "$CATALINA_PID" ]致使這段語句什麼都沒作啊!!!!!
第五處:
#這段代碼就是涉及-force的核心代碼了 if [ $FORCE -eq 1 ]; then if [ -z "$CATALINA_PID" ]; then echo "Kill failed: \$CATALINA_PID not set" else if [ -f "$CATALINA_PID" ]; then PID=`cat "$CATALINA_PID"` echo "Killing Tomcat with the PID: $PID" kill -9 $PID #強制執行的核心命令 rm -f "$CATALINA_PID" >/dev/null 2>&1 if [ $? != 0 ]; then echo "Tomcat was killed but the PID file could not be removed." fi fi fi fi #從中就能夠看出,sh -x輸出的Kill failed: $CATALINA_PID not set是怎麼來的
總結下,$CATALINA_PID在整個代碼中的做用:
1.在tomcat啓動時會寫入$CATALINA_PID,可是假設咱們的環境是多tomcat項目或$CATALINA_PID爲空
2.stop代碼中,檢查$CATALINA_PID是否爲空字符,是的話什麼都不作
3.sstop代碼中,檢查$CATALINA_PID是否爲空字符,是的話什麼都不作
4.force代碼中,檢查$CATALINA_PID是否爲空字符,是的話就報錯
也就是說只要沒有保存中這個項目的PID,那麼正常stop中止不了,-force也是沒有用的。
那麼該如何解決呢?直接給$CATALINA_PID付PID的值,那麼看結果:
+ FORCE=1 + '[' '!' -z 12031 ']' + '[' -f 12031 ']' + echo '$CATALINA_PID was set but the specified file does not exist. Is Tomcat running? Stop aborted.' $CATALINA_PID was set but the specified file does not exist. Is Tomcat running? Stop aborted.
涉及到的代碼:
if [ -f "$CATALINA_PID" ]; then if [ -s "$CATALINA_PID" ]; then kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1 #kill -0 pid 不發送任何信號,可是系統會進行錯誤檢查。 if [ $? -gt 0 ]; then echo "PID file found but no matching process was found. Stop aborted." exit 1 fi else echo "PID file is empty and has been ignored." fi else echo "\$CATALINA_PID was set but the specified file does not exist. Is Tomcat running? Stop aborted." exit 1 #$CATALINA_PID不是個文件,因此很差意思,我退出了....
原來$CATALINA_PID還必須是個文件,那麼咱們可不能夠建這麼一個文件呢?
在catalina.sh腳本的代碼前,加入如下語句:
######################################################################################### if [ -z "$CATALINA_PID" ]; then CATALINA_PID=$PRGDIR/CATALINA_PID cat $CATALINA_PID fi
######################################################################################
結果:tomcat中止執行成功,完成結束進程任務
總結:
在我看到的很到部署tomcat的文章中,還沒發現有關於設置$CATALINA_PID文件路徑的提示(也許是我看到的少),可是此處我要建議小夥伴們,在寫tomcat啓動、中止、重啓的腳本的時候,必定要注意這個變量。