如果你們公司服務器上跑的是java的代碼,那多半會使用Tomcat,而Tomcat出現問題,我們就不得不去查看Tomcat日誌。Tomcat有一個總日誌叫catalina out,它記錄了Tomcat相關的信息,包括正確的和錯誤的。該案例的需求背景是:
服務器上跑着4個Tomcat實例,目錄結構如下:
/opt/TOMCAT/ ├── crontabs ├── t1 ├── t2 ├── t3 └── t4
而catalina out所在路徑如下:
/opt/TOMCAT/t1/logs/catalina.out /opt/TOMCAT/t2/logs/catalina.out /opt/TOMCAT/t3/logs/catalina.out /opt/TOMCAT/t4/logs/catalina.out
具體需求如下:
1)腳本可以取Tomcat實例t1-t4的日誌,通過參數指定是哪一個。
2)腳本可以自定義取日誌的起始位置,比如取今天早上10點之後到現在的日誌,要求提供的時間爲24小時制。
3)腳本可以自定義取日誌的起始和結束位置,比如取今天早上9點到20點的日誌,要求提供的時間爲24小時制。
4)第一個參數爲哪一個Tomcat(t1、t2、t3、t4),第二個參數爲起始時間點(只考慮當天的時間),第三個參數爲結束時間點,可以省略,如果省略則爲當前時間點。
5)提供的時間點需要判斷合法性,即必須爲12:00:00這種格式。
日誌片段如下:
Aug 22,2019 15:58:33 PM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["http-bio-8080"] Aug 22,2019 16:38:23 PM org.apahce.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["ajp-bio-8009"] Aug 22,2019 16:45:46 PM org.apahce.catalina.startup.Catalina start INFO: Server startup in 2102 ms
知識點一:Tomcat介紹和安裝
Tomcat是一個web容器,我們主要用它來運行servlet和JSP。Tomcat本身也是一個http服務器,它可以像Apache或者Nginx那樣解析HTML網頁、JS、CSS以及圖片等元素,但它最主要的功能是用來運行Servlet或JSP。關於Tomcat涉及到一些JAVA相關的概念,下面簡單做一個羅列。
JAVAEE Java Plateform Enterprise Edition 企業版本,用來做網站的 JAVASE Java Plateform Standard Edition 標準版本,用來做電腦上運行的軟件的 JAVAME Java Plateform Micro Edition 微型版本,做手機軟件的 JDK Java Development kit Java的開發和運行環境,JDK=Java開發工具+JRE JRE Java Runtime Environment Java程序的運行環境,包括Java運行所需要的類庫和JVM JVM Java虛擬機 jar (Java application archive)包含class和一些資源和配置文件的壓縮包 war (web application archive)與jar基本相同,會包含全部的web應用程序,Tomcat會自動將其部署
上面提到了Servlet和JSP,它們二者的區別主要有以下幾點:
1)在html代碼中內嵌Java代碼就是jsp,而servlet是純Java代碼寫的。
2)jsp主要用來展現頁面效果,而servlet主要負責邏輯控制。
3)用戶第一次運行jsp時,會自動轉換爲servlet代碼,所以說jsp本質上就是一種servlet。
4)第一次訪問servlet時,會將其編譯爲類文件,後續可以直接訪問類文件。
關於Tomcat的安裝,這裏簡單列一下步驟,供參考:
1.安裝jdk(以下方法二選一)
方法一:yum安裝java-1.8.0-openjdk
# yum install -y java-1.8.0-openjdk
方法二:安裝Oracle官方版jdk
1)到https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 下載jdk8
2)解壓並改名/usr/local/jdk1.8
3)編輯配置文件/etc/profile,增加如下內容到最後:
JAVA_HOME=/usr/local/jdk1.8/ JAVA_BIN=/usr/local/jdk1.8/bin JRE_HOME=/usr/local/jdk1.8/jre PATH=$PATH:/usr/local/jdk1.8/bin:/usr/local/jdk1.8/jre/bin CLASSPATH=/usr/local/jdk1.8/jre/lib:/usr/local/jdk1.8/lib:/usr/local/jdk1.8/jre/lib/charsets.jar
2.安裝Tomcat(版本爲9.0)
1)下載二進制包,下載地址爲https://tomcat.apache.org/download-90.cgi
2)解壓並改名/usr/local/tomcat
3)啓動/usr/local/tomcat/bin/startup.sh
知識點二:Tomcat單擊多實例
單擊多實例,就是在一臺服務器上跑多個Tomcat服務。其實想要運行Tomcat,不僅需要Tomcat的主程序文件(比如/usr/local/tomcat/bin下的二進制文件),還需要配置文件等輔助類文件。要想跑多個Tomcat服務,可以只需要一份主程序文件即可,不同的Tomcat服務使用不同的配置文件即可。所以,要想實現單擊多實例,可以這樣規劃一下目錄,如圖:
其中CATALINA_HOME指的是Tomcat安裝目錄(如果你按照我的方法安裝,那麼就是在/usr/local/tomcat),CATALINA_BASE爲實例所在目錄。CATALINA_HOME路徑下只需要包含bin和lib目錄,而CATALINA_BASE只存放conf、webapps、logs等這些文件,這樣部署的好處在於升級方便,配置及安裝文件間互不影響,在不影響Tomcat實例的前提下,替換掉CATALINA_HOME中的安裝文件。
具體的部署步驟如下:
1.創建實例目錄
# mkdir -p /data/tomcat-instance # mkdir /data/tomcat-instance/www.123.com # cd !$ # cp -r /usr/local/tomcat/conf /data/tomcat-instance/www.123.com/
2.創建Tomcat服務相關目錄
# mkdir -p /data/tomcat-instance/www.123.com/{common,logs,temp,server,shared,webapps,work}
3.創建啓動和關閉腳本
# cd /data/tomcat-instance/www.123.com # vim start.sh //啓動腳本 #!/bin/bash export CATALINA_HOME=/usr/local/tomcat export CATALINA_BASE=/data/tomcat-instance/www.123.com TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2 }'` if [ -n "$TOMCAT_ID" ] then echo "tomcat(${TOMCAT_ID}) still running now , please shutdown it first"; exit 2; else $CATALINA_HOME/bin/startup.sh if [ "$?" = "0" ]; then echo "start succeed" else echo "start failed" fi fi # vim shutdown.sh //關閉腳本 #!/bin/bash export CATALINA_HOME=/usr/local/tomcat export CATALINA_BASE=/data/tomcat-instance/www.123.com TOMCAT_ID=`ps aux |grep "java"|grep "Dcatalina.base=$CATALINA_BASE "|grep -v "grep"|awk '{ print $2}'` if [ -n "$TOMCAT_ID" ] ; then TOMCAT_STOP_LOG=`$CATALINA_HOME/bin/shutdown.sh` if [ "$?" = "0" ]; then echo "stop succeed" else echo "stop failed" fi else echo "Tomcat instance not found" exit fi
4.編輯配置文件
# cd /data/tomcat-instance/www.123.com/conf # vim server.xml //修改三個端口,目的是爲了不和其他實例衝突
有了第一個實例後,第二個實例可以直接複製/data/tomcat-instance/www.123.com目錄,然後修改對應的配置、啓動腳本、停止腳本內容。
知識點三:shell腳本的參數個數
在前面的案例中多次用到$1,$2,即shell腳本的參數。和參數相關的還有一個常用的概念,那就是shell腳本參數的個數。先看示例腳本:
# vim pa_nu.sh #!/bin/bash echo "腳本有$#個參數"
執行腳本,過程如下:
# sh pa_nu.sh 1 a 腳本有2個參數 # sh pa_nu.sh 腳本有0個參數 # sh pa_nu.sh a b c 腳本有3個參數
所以,結論就是在shell腳本中用$#表示腳本的參數個數。
知識點四:判斷一個時間是否合法
如果使用傳統的方法,去比對時、分、秒的範圍是可以做到,但是這樣太繁瑣,有一個簡單的方法,如下:
# date -d "19:60:" +%s date: 無效的日期"19:60:" # date -d "19:59" +%s 1566561540
就是用date命令來做。
知識點五:將24小時制的時間轉換爲12小時制
直接看命令,如下:
# date -d "17:13:14" +%r 05:13:14 PM
也可以直接判斷一個時間是AM還是PM
# date -d "17:13:14" +%p //小寫字母p PM
如果想用小寫的,也可以做到:
# date -d "9:10:33" +%P //大寫字母P am
知識點六:比較兩個時間大小
比較時間大小,只能通過時間戳來實現,如下:
# t1=`date -d "13:22:32" +%s` # t2=`date -d "15:00:00" +%s` # if [ $t1 -lt $t2 ]; then echo "t1比t2要早"; else echo "t1比t2要晚"; fi t1比t2要早 # if [ $t1 -lt $t2 ]; then echo "t1比t2要早"; else echo "t1比t2要晚"; fi t1比t2要晚
本案例參考腳本
#!/bin/bash #截取指定Tomcat的日誌片段 #作者: #日期: LANG=en logfile="/opt/TOM/$1/logs/catalina.out" #將當天的英文月、數字日期、數字年作爲變量賦值給d_mdy d_mdy=`date "+%b %d, %Y"` #判斷參數個數 if [ $# -ne 2 ] && [ $# -ne 3 ] then echo "你提供的參數個數不對,請提供2個或者3個參數。例:sh $0 t1 08:01:00 14:00:00" exit 1 fi #判斷第一個參數是否符合要求 if ! echo $1|grep -qE '^t1$|^t2$|^t3$|^t4$' then echo "第一個參數必須是t1、t2、t3或t4" exit 1 fi #判斷時間有效性 judge_time() { date -d "$1" +%s &>/dev/null if [ $? -ne 0 ] then echo "你提供的時間$1格式不正確" exit 1 fi } #判斷提供的時間點是否在日誌中出現 judge_time_in_log() { if ! grep -q "$d_mdy $(tr_24_12 $1)" $logfile then echo "你提供的時間$1在日誌$logfile中不曾出現,請換一個時間點" exit 1 fi } #將24小時制時間轉換爲12小時 tr_24_12() { date -d "$1" +%r } #判斷第2個參數是否合法 judge_time $2 #判斷起始時間點是否出現在日誌裏 judge_time_in_log $2 #如果提供第3個參數 if [ $# -eq 3 ] then #判斷第3個參數是否合法 judge_time $3 #判斷起始時間是否早於結束時間 t1=`date -d "$2" +%s` t2=`date -d "$3" +%s` if [ $t2 -lt $t1 ] then echo "你提供的時間$2比$3要晚,應該把早的時間放到前面" exit fi #判斷提供的結束時間點是否出現在日誌中 judge_time_in_log $3 fi #取起始時間所在行行號 begin_n=`grep -n "$d_mdy $(tr_24_12 $2)" $logfile|head -1|awk -F ':' '{print $1}'` #取結束時間所在行行號,並用sed截取日誌內容 if [ $# -eq 3 ] then n=`grep -n "$d_mdy $(tr_24_12 $3)" $logfile|tail -1|awk -F ':' '{print $1}'` #結束日期所在行的下一行纔是日誌的內容 end_n=$[$n+1] sed -n "$begin_n,$end_n"p $logfile else sed -n "$begin_n,$"p $logfile fi