如果你们公司服务器上跑的是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