案例十九:分析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/t3/logs/catalina.out
/opt/TOMCAT/t4/logs/catalina.out
/opt/TOMCAT/t2/logs/catalina.out

具体需求如下:
1)脚本可以取Tomcat实例t1-t4的日志,通过参数指定是哪一个
2)脚本可以自定义取日志的起始位置,比如取今天早上10点之后到现在的日志,要求提供的时间为24小时制
3)脚本可以自定义取日志的起始和结束位置,比如取今天早上9点到晚上8点的日志,要求提供的时间为24小时制
4)第一个参数为哪一个Tomcat(t1,t2,t3,t4),第二个参数为起始时间点(只考虑当天的时间),第三个参数位结束时间点,可以省略,如果省略则为当前时间点
5)提供的时间点需要判断合法性,即必须为18:03:20这样的格式

日志片段如下:

Oct 29, 2018 01:52:24 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Oct 29, 2018 01:52:24 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Oct 29, 2018 01:52:24 PM org.apache.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 Developmnet 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(以下方法二选一)
方法1:yum 安装 java-1.8.0-openjdk

# yum install -y java-1.8.0-openjdk

方法2:安装oracle官方jdk
1)到 http://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.创建启动和关闭脚本

# vi /data/tomcat-instance/www.123.com/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 "sart failed"
    fi
fi

# vi /data/tomcat-instance/www.123.com/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.编辑配置文件

# vi /data/tomcat-instance/www.123.com/conf/server.xml //修改三个端口,目的是为了不和其他实例冲突

有了第一个实例后,第二个实例可以直接复制/data/tomcat-instance/www.123.com 目录,然后修改对应的配置、启动脚本、停止脚本内容。

知识点三:shell脚本的参数个数

在前面的案例中多次用到$1,$2...,即shell脚本的参数。和参数相关的还有一个常用的概念,那就是shell脚本参数的个数。先来看示例脚本:

# vi 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
1541678340

没错,就是用date命令来做。

知识点五:将24小时制的时间转换为12小时制

不解释,直接看命令吧,如下:

# date -d "19:59:33" +%r
07:59:33 PM

当然,我们也可以直接判断一个时间是AM还是PM

# date -d "19:59:33" +%p  //注意,这个是小写的p
PM

如果想用小写的,也可以做到

# date -d "9:10:00" +%P  //注意,这个是大写的P
am

知识点六:比较两个时间大小

比较时间大小,只能通过时间戳来实现,如下

# t1=`date -d "13:59:59" +%s`
# t2=`date -d "15:00:00" +%s`
# if [ $t1 -lt $t2 ]; then echo "t1比t2要早"; else echo "t1比t2要晚"; fi
t1比t2要早
# t2=`date -d "10:00:00" +%s`
# if [ $t1 -lt $t2 ]; then echo "t1比t2要早"; else echo "t1比t2要晚"; fi
t1比t2要晚

本案例参考脚本

#!/bin/bash
#截取指定Tomcat的日志片段
#作者:阿铭
#日期:2018-11-08

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

说明:本脚本没有考虑起始时间和结束时间包含日期的情况,请你发散思维,将需求继续复杂化,把脚本写的更加完美。

版权声明:
作者:WaterBear
链接:https://l-t.top/2833.html
来源:雷霆运维
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录