案例十九、分析Tomcat日志

如果你们公司服务器上跑的是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服务使用不同的配置文件即可。所以,要想实现单击多实例,可以这样规划一下目录,如图:

111.png

其中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


猜你喜欢

转载自blog.51cto.com/13576245/2432335