Linux 日志切割工具cronolog详解

时间:2022-11-01 08:00:55

一、前言

二、cronolog 简介

三、cronolog 特点

四、cronolog 安装

五、cronolog 使用

六、cronolog 总结

注,操作系统 CentOS 6.4 x86_64,软件版本 cronolog 1.6.2,软件下载http://cronolog.org/download/index.html


一、前言

大家都知道apache服务器,默认日志文件是不分割的,一个整文件既不易于管理,也不易于分析统计。本博文主要讲解Web服务器日志切割工具cronolog,下面我们就来详细的讲解一下。


二、cronolog 简介

Welcome to cronolog.org, the home of the cronolog web log rotation program.cronolog is a simple filter program that reads log file entries from standard input and writes each entry to the output file specified by a filename template and the current date and time. When the expanded filename changes, the current file is closed and a new one opened. cronolog is intended to be used in conjunction with a Web server, such as Apache, to split the access log into daily or monthly logs.


cronolog 是一个简单的过滤程序,读取日志文件条目从标准输入和输出的每个条目并写入指定的日志文件的文件名模板和当前的日期和时间。当扩展文件名的变化,目前的文件是关闭,新开辟的。cronolog 旨在和一个Web服务器一起使用,如Apache,分割访问日志为每天或每月的日志。


三、cronolog 特点

cronolog主要和Web服务器配置使用,特别是Apache服务器,Apache 默认日志文件是不分割的,一个整文件既不易于管理,也不易于分析统计。安装cronolog后,可以将日志文件按时间分割,易于管理和分析。下面是与Apache配置的一些指令:

1
2
TransferLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/access.log"
ErrorLog    "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/errors.log"

下面是具体案例,

1
2
/web/logs/2002/12/31/access .log /web/logs/2002/12/31/errors .log
/web/logs/2003/01/01/access .log /web/logs/2003/01/01/errors .log


四、cronolog 安装

1.安装yum源

1
2
3
4
5
6
[root@node6 src] # yum install -y wget vim
[root@node6 src] # wget http://ftp.sjtu.edu.cn/fedora/epel/6/i386/epel-release-6-8.noarch.rpm
[root@node6 src] # rpm -ivh epel-release-6-8.noarch.rpm
warning: epel-release-6-8.noarch.rpm: Header V3 RSA /SHA256 Signature, key ID 0608b895: NOKEY
Preparing...                ########################################### [100%]
    1:epel-release           ########################################### [100%]

2.安装ntp

1
[root@node6 src] # yum install -y ntp

3.时间同步

1
2
[root@node6 src] # ntpdate 202.120.2.101
28 Dec 17:59:17 ntpdate[1413]: step time server 202.120.2.101 offset -25666.776448 sec

4.安装cronolog

(1).直接用yum安装

1
[root@node6 src] # yum install -y cronolog httpd

(2).源码安装

1
2
3
4
5
6
7
[root@node6 src] # wget http://cronolog.org/download/cronolog-1.6.2.tar.gz
[root@node6 src] # tar xf cronolog-1.6.2.tar.gz
[root@node6 src] # cd cronolog-1.6.2
[root@node6 cronolog-1.6.2] # ./configure
[root@node6 cronolog-1.6.2] # make && make install
[root@localhost ~] # which cronolog
/usr/local/sbin/cronolog

好了,到这里我们的cronolog就安装完成了,下面我们来说一下cronolog如何使用。


五、cronolog 使用

(1).基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@node6 ~] # cronolog -h
usage: cronolog [OPTIONS] logfile-spec
    -H NAME,   --hardlink=NAME maintain a hard link from NAME to current log
    -S NAME,   -- symlink =NAME  maintain a symbolic link from NAME to current log
    -P NAME,   --prev- symlink =NAME  maintain a symbolic link from NAME to previous log
    -l NAME,   --link=NAME     same as -S /--symlink
    -h,        --help          print this help, then exit
    -p PERIOD, --period=PERIOD set the rotation period explicitly
    -d DELAY,  --delay=DELAY   set the rotation period delay
    -o,        --once-only     create single output log from template (not rotated)
    -x FILE,   --debug=FILE    write debug messages to FILE
                               ( or to standard error if FILE is "-" )
    -a,        --american         American date formats
    -e,        --european         European date formats (default)
    -s,    --start- time =TIME   starting time
    -z TZ, -- time -zone=TZ      use TZ for timezone
    -V,      --version         print version number, then exit

cronolog 一般是采取管道的方式来工作的,采用如下的形式:

1
[root@node6 ~] # loggenerator | cronolog log_file_pattern

其中,loggenerator为产生log的程序,而log_file_pattern是日志文件的路径,可以在其中加入cronolog所支持的时间相关的pattern字符,如/www/log/%y/%m/%d/access.log。其pattern为%字符后跟一特殊字符,简述如下:

转义符:  

1
2
3
%    %字符
n    换行
t    水平制表符

时间域:  

1
2
3
4
5
6
7
H    小时(00..23)
I    小时(01..12)
p    该locale下的AM或PM标识
M    分钟(00..59)
S    秒 (00..61, which allows for leap seconds)
X    该locale下时间表示符(e.g.: "15:12:47" )
Z    时区。若时区不能确定,则无意义

日期域:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a    该locale下的工作日简名(e.g.: Sun..Sat)
A    该locale下的工作日全名(e.g.: Sunday ..  Satur-ay)
b    该locale下的月份简称(e.g.: Jan .. Dec)
B    该locale下的月份全称(e.g.:  January .. December)
c    该locale下的日期和时间(e.g.: "Sun Dec 15  14:12:47 GMT 1996" )
d    当月中的天数 (01 .. 31)
j    当年中的天数 (001 .. 366)
m    月数 (01 .. 12)
U    当年中的星期数,以周日作为一周开始,其中第一周为首个含星期天的星期(00..53)
W    当年中的星期数,以星期一作为一周的开始,其中第一周为首个含星期天的星期(00..53)
w    工作日数(0 .. 6, 0表示星期天)
x    该locale下的日期表示(e.g. "13/04/97" )
y    两位数的年份(00 .. 99)
Y    四位数的年份(1970 .. 2038)

(2).结合apache使用

编辑httpd.conf文件,将其中的

1
2
3
4
[root@localhost ~] # vim /usr/local/apache2/conf/httpd.conf
将默认日志: CustomLog "logs/access_log" combined
修改为:CustomLog "|/usr/local/sbin/cronolog /log/www/access_%Y%m%d.log" combined 即可。其中%Y%m%d为日志文件分割方式,即为“年月日”。
[root@localhost ~] # /usr/local/apache2/bin/apachectl restart

(3).下面是效果

1
2
3
4
5
6
7
[root@localhost ~] # cd /log/www/
[root@localhost www] # ll
total 15072
-rw-r--r-- 1 root root   16028 Dec 26 15:16 access_20131225.log
-rw-r--r-- 1 root root 2406307 Dec 26 23:59 access_20131226.log
-rw-r--r-- 1 root root 8292792 Dec 27 23:59 access_20131227.log
-rw-r--r-- 1 root root 4682211 Dec 28 18:56 access_20131228.log


六、cronolog 总结

好了,到这里我们的cronolog工具就讲解完成了。有博友会问为什么不用apache自带的日志分割工具?apache自带的日志分割工具rotatelogs,据专家说在进行日志切割时容易丢日志,所以这里我们就用cronolog来做日志切割。最后,希望大家有所收获^_^……


安装过程:

解压

unzip cronolog-1.6.2.zip
[root@localhost src]# cd cronolog-1.6.2
[root@localhost cronolog-1.6.2]# ls
aclocal.m4  AUTHORS  ChangeLog  configure  configure.in  COPYING  cronolog.spec  doc  INSTALL  install-sh  lib  Makefile.am  Makefile.in  missing  mkinstalldirs  NEWS  README  src  testsuite  TODO
[root@localhost cronolog-1.6.2]# ll
total 192
-rwxr-xr-x 1 root root  3539 May  4  2001 aclocal.m4
-rwxr-xr-x 1 root root    50 Mar  8  1998 AUTHORS
-rwxr-xr-x 1 root root  1685 Dec 20  1999 ChangeLog
-rwxr-xr-x 1 root root 71059 May  4  2001 configure
-rwxr-xr-x 1 root root  1810 May  4  2001 configure.in
-rwxr-xr-x 1 root root 18043 Apr 10  1997 COPYING
-rwxr-xr-x 1 root root  1685 May  4  2001 cronolog.spec
drwxr-xr-x 2 root root  4096 May  4  2001 doc
-rwxr-xr-x 1 root root  7463 Apr 12  1997 INSTALL
-rwxr-xr-x 1 root root  5585 Apr 10  1997 install-sh
drwxr-xr-x 2 root root  4096 May  4  2001 lib
-rwxr-xr-x 1 root root   167 May  4  2001 Makefile.am
-rwxr-xr-x 1 root root 10909 May  4  2001 Makefile.in
-rwxr-xr-x 1 root root  6283 Jul 12  2000 missing
-rwxr-xr-x 1 root root   729 Apr 10  1997 mkinstalldirs
-rwxr-xr-x 1 root root  2134 Dec 20  1999 NEWS
-rwxr-xr-x 1 root root 10108 Dec 20  1999 README
drwxr-xr-x 2 root root  4096 May  4  2001 src
drwxr-xr-x 2 root root  4096 May  4  2001 testsuite
-rwxr-xr-x 1 root root   755 Dec 20  1999 TODO
[root@localhost cronolog-1.6.2]# ./configure
creating cache ./config.cache
checking for a BSD compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... yes
checking for working aclocal... found
checking for working autoconf... found
checking for working automake... found
checking for working autoheader... found
checking for working makeinfo... missing
checking for gcc... gcc
checking whether the C compiler (gcc  ) works... yes
checking whether the C compiler (gcc  ) is a cross-compiler... no
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
checking for a BSD compatible install... /usr/bin/install -c
checking whether ln -s works... yes
checking for ranlib... ranlib
checking for perl... /usr/bin/perl
checking how to run the C preprocessor... gcc -E
checking for ANSI C header files... yes
checking whether stat file-mode macros are broken... no
checking whether time.h and sys/time.h may both be included... yes
checking whether struct tm is in sys/time.h or time.h... time.h
checking for tm_zone in struct tm... yes
checking for fcntl.h... yes
checking for limits.h... yes
checking for unistd.h... yes
checking for working const... yes
checking for size_t... yes
checking whether struct tm is in sys/time.h or time.h... (cached) time.h
checking for strftime... yes
checking for vprintf... yes
checking for mkdir... yes
checking for mktime... yes
checking for putenv... yes
checking for strptime... yes
checking for localtime_r... yes
updating cache ./config.cache
creating ./config.status
creating Makefile
creating lib/Makefile
creating src/Makefile
creating doc/Makefile
creating testsuite/Makefile
creating src/cronosplit
[root@localhost cronolog-1.6.2]# make && make install
Making all in lib
make[1]: Entering directory `/usr/src/cronolog-1.6.2/lib'
gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_TM_ZONE=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1 -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1 -DHAVE_STRPTIME=1 -DHAVE_LOCALTIME_R=1  -I. -I.      -g -O2 -c getopt.c
gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_TM_ZONE=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1 -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1 -DHAVE_STRPTIME=1 -DHAVE_LOCALTIME_R=1  -I. -I.      -g -O2 -c getopt1.c
rm -f libutil.a
ar cru libutil.a getopt.o getopt1.o
ranlib libutil.a
make[1]: Leaving directory `/usr/src/cronolog-1.6.2/lib'
Making all in src
make[1]: Entering directory `/usr/src/cronolog-1.6.2/src'
gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_TM_ZONE=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1 -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1 -DHAVE_STRPTIME=1 -DHAVE_LOCALTIME_R=1  -I. -I.  -I../lib    -g -O2 -c cronotest.c
gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_TM_ZONE=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1 -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1 -DHAVE_STRPTIME=1 -DHAVE_LOCALTIME_R=1  -I. -I.  -I../lib    -g -O2 -c cronoutils.c
cronoutils.c: In function ‘parse_time’:
cronoutils.c:673: warning: cast to pointer from integer of different size
gcc  -g -O2  -o cronotest  cronotest.o cronoutils.o ../lib/libutil.a
gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_TM_ZONE=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1 -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1 -DHAVE_STRPTIME=1 -DHAVE_LOCALTIME_R=1  -I. -I.  -I../lib    -g -O2 -c cronolog.c
gcc  -g -O2  -o cronolog  cronolog.o cronoutils.o ../lib/libutil.a
make[1]: Leaving directory `/usr/src/cronolog-1.6.2/src'
Making all in doc
make[1]: Entering directory `/usr/src/cronolog-1.6.2/doc'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/usr/src/cronolog-1.6.2/doc'
Making all in testsuite
make[1]: Entering directory `/usr/src/cronolog-1.6.2/testsuite'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/usr/src/cronolog-1.6.2/testsuite'
make[1]: Entering directory `/usr/src/cronolog-1.6.2'
make[1]: Nothing to be done for `all-am'.
make[1]: Leaving directory `/usr/src/cronolog-1.6.2'
Making install in lib
make[1]: Entering directory `/usr/src/cronolog-1.6.2/lib'
make[2]: Entering directory `/usr/src/cronolog-1.6.2/lib'
make[2]: Nothing to be done for `install-exec-am'.
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/usr/src/cronolog-1.6.2/lib'
make[1]: Leaving directory `/usr/src/cronolog-1.6.2/lib'
Making install in src
make[1]: Entering directory `/usr/src/cronolog-1.6.2/src'
make[2]: Entering directory `/usr/src/cronolog-1.6.2/src'
/bin/sh ../mkinstalldirs /usr/local/sbin
  /usr/bin/install -c  cronolog /usr/local/sbin/cronolog
/bin/sh ../mkinstalldirs /usr/local/sbin
 /usr/bin/install -c  cronosplit /usr/local/sbin/cronosplit
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/usr/src/cronolog-1.6.2/src'
make[1]: Leaving directory `/usr/src/cronolog-1.6.2/src'
Making install in doc
make[1]: Entering directory `/usr/src/cronolog-1.6.2/doc'
make[2]: Entering directory `/usr/src/cronolog-1.6.2/doc'
make[2]: Nothing to be done for `install-exec-am'.
/bin/sh ../mkinstalldirs /usr/local/info
mkdir /usr/local/info
 /usr/bin/install -c -m 644 ./cronolog.info /usr/local/info/cronolog.info
 install-info --info-dir=/usr/local/info /usr/local/info/cronolog.info
make  install-man1
make[3]: Entering directory `/usr/src/cronolog-1.6.2/doc'
/bin/sh ../mkinstalldirs /usr/local/man/man1
mkdir /usr/local/man
mkdir /usr/local/man/man1
 /usr/bin/install -c -m 644 ./cronolog.1m /usr/local/man/man1/cronolog.1m
 /usr/bin/install -c -m 644 ./cronosplit.1m /usr/local/man/man1/cronosplit.1m
make[3]: Leaving directory `/usr/src/cronolog-1.6.2/doc'
make[2]: Leaving directory `/usr/src/cronolog-1.6.2/doc'
make[1]: Leaving directory `/usr/src/cronolog-1.6.2/doc'
Making install in testsuite
make[1]: Entering directory `/usr/src/cronolog-1.6.2/testsuite'
make[2]: Entering directory `/usr/src/cronolog-1.6.2/testsuite'
make[2]: Nothing to be done for `install-exec-am'.
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/usr/src/cronolog-1.6.2/testsuite'
make[1]: Leaving directory `/usr/src/cronolog-1.6.2/testsuite'
make[1]: Entering directory `/usr/src/cronolog-1.6.2'
make[2]: Entering directory `/usr/src/cronolog-1.6.2'
make[2]: Nothing to be done for `install-exec-am'.
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/usr/src/cronolog-1.6.2'
make[1]: Leaving directory `/usr/src/cronolog-1.6.2'
[root@localhost cronolog-1.6.2]# which cronolog
/usr/local/sbin/cronolog
[root@localhost cronolog-1.6.2]#


 catalina.sh

#!/bin/sh

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# -----------------------------------------------------------------------------
# Control Script for the CATALINA Server
#
# Environment Variable Prerequisites
#
#   Do not set the variables in this script. Instead put them into a script
#   setenv.sh in CATALINA_BASE/bin to keep your customizations separate.
#
#   CATALINA_HOME   May point at your Catalina "build" directory.
#
#   CATALINA_BASE   (Optional) Base directory for resolving dynamic portions
#                   of a Catalina installation.  If not present, resolves to
#                   the same directory that CATALINA_HOME points to.
#
#   CATALINA_OUT    (Optional) Full path to a file where stdout and stderr
#                   will be redirected.
#                   Default is $CATALINA_BASE/logs/catalina.out
#
#   CATALINA_OPTS   (Optional) Java runtime options used when the "start",
#                   "run" or "debug" command is executed.
#                   Include here and not in JAVA_OPTS all options, that should
#                   only be used by Tomcat itself, not by the stop process,
#                   the version command etc.
#                   Examples are heap size, GC logging, JMX ports etc.
#
#   CATALINA_TMPDIR (Optional) Directory path location of temporary directory
#                   the JVM should use (java.io.tmpdir).  Defaults to
#                   $CATALINA_BASE/temp.
#
#   JAVA_HOME       Must point at your Java Development Kit installation.
#                   Required to run the with the "debug" argument.
#
#   JRE_HOME        Must point at your Java Runtime installation.
#                   Defaults to JAVA_HOME if empty. If JRE_HOME and JAVA_HOME
#                   are both set, JRE_HOME is used.
#
#   JAVA_OPTS       (Optional) Java runtime options used when any command
#                   is executed.
#                   Include here and not in CATALINA_OPTS all options, that
#                   should be used by Tomcat and also by the stop process,
#                   the version command etc.
#                   Most options should go into CATALINA_OPTS.
#
#   JAVA_ENDORSED_DIRS (Optional) Lists of of colon separated directories
#                   containing some jars in order to allow replacement of APIs
#                   created outside of the JCP (i.e. DOM and SAX from W3C).
#                   It can also be used to update the XML parser implementation.
#                   Defaults to $CATALINA_HOME/endorsed.
#
#   JPDA_TRANSPORT  (Optional) JPDA transport used when the "jpda start"
#                   command is executed. The default is "dt_socket".
#
#   JPDA_ADDRESS    (Optional) Java runtime options used when the "jpda start"
#                   command is executed. The default is 8000.
#
#   JPDA_SUSPEND    (Optional) Java runtime options used when the "jpda start"
#                   command is executed. Specifies whether JVM should suspend
#                   execution immediately after startup. Default is "n".
#
#   JPDA_OPTS       (Optional) Java runtime options used when the "jpda start"
#                   command is executed. If used, JPDA_TRANSPORT, JPDA_ADDRESS,
#                   and JPDA_SUSPEND are ignored. Thus, all required jpda
#                   options MUST be specified. The default is:
#
#                   -agentlib:jdwp=transport=$JPDA_TRANSPORT,
#                       address=$JPDA_ADDRESS,server=y,suspend=$JPDA_SUSPEND
#
#   CATALINA_PID    (Optional) Path of the file which should contains the pid
#                   of the catalina startup java process, when start (fork) is
#                   used
#
#   LOGGING_CONFIG  (Optional) Override Tomcat's logging config file
#                   Example (all one line)
#                   LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties"
#
#   LOGGING_MANAGER (Optional) Override Tomcat's logging manager
#                   Example (all one line)
#                   LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
# -----------------------------------------------------------------------------

JAVA_OPTS="-server -Xms1048m -Xmx4096m -XX:MaxNewSize=512m -XX:PermSize=64M -XX:MaxPermSize=256M"
# OS specific support.  $var _must_ be set to either true or false.
cygwin=false
darwin=false
os400=false
case "`uname`" in
CYGWIN*) cygwin=true;;
Darwin*) darwin=true;;
OS400*) os400=true;;
esac

# resolve links - $0 may be a softlink
PRG="$0"

while [ -h "$PRG" ]; do
  ls=`ls -ld "$PRG"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    PRG="$link"
  else
    PRG=`dirname "$PRG"`/"$link"
  fi
done

# Get standard environment variables
PRGDIR=`dirname "$PRG"`

# Only set CATALINA_HOME if not already set
[ -z "$CATALINA_HOME" ] && CATALINA_HOME=`cd "$PRGDIR/.." >/dev/null; pwd`

# Copy CATALINA_BASE from CATALINA_HOME if not already set
[ -z "$CATALINA_BASE" ] && CATALINA_BASE="$CATALINA_HOME"

# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=

if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
  . "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
  . "$CATALINA_HOME/bin/setenv.sh"
fi

# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin; then
  [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
  [ -n "$JRE_HOME" ] && JRE_HOME=`cygpath --unix "$JRE_HOME"`
  [ -n "$CATALINA_HOME" ] && CATALINA_HOME=`cygpath --unix "$CATALINA_HOME"`
  [ -n "$CATALINA_BASE" ] && CATALINA_BASE=`cygpath --unix "$CATALINA_BASE"`
  [ -n "$CLASSPATH" ] && CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi

# For OS400
if $os400; then
  # Set job priority to standard for interactive (interactive - 6) by using
  # the interactive priority - 6, the helper threads that respond to requests
  # will be running at the same priority as interactive jobs.
  COMMAND='chgjob job('$JOBNAME') runpty(6)'
  system $COMMAND

  # Enable multi threading
  export QIBM_MULTI_THREADED=Y
fi

# Get standard Java environment variables
if $os400; then
  # -r will Only work on the os400 if the files are:
  # 1. owned by the user
  # 2. owned by the PRIMARY group of the user
  # this will not work if the user belongs in secondary groups
  . "$CATALINA_HOME"/bin/setclasspath.sh
else
  if [ -r "$CATALINA_HOME"/bin/setclasspath.sh ]; then
    . "$CATALINA_HOME"/bin/setclasspath.sh
  else
    echo "Cannot find $CATALINA_HOME/bin/setclasspath.sh"
    echo "This file is needed to run this program"
    exit 1
  fi
fi

# Add on extra jar files to CLASSPATH
if [ ! -z "$CLASSPATH" ] ; then
  CLASSPATH="$CLASSPATH":
fi
CLASSPATH="$CLASSPATH""$CATALINA_HOME"/bin/bootstrap.jar

if [ -z "$CATALINA_OUT" ] ; then
  CATALINA_OUT="$CATALINA_BASE/logs/catalina.out.%Y-%m-%d"
fi
echo "$CATALINA_OUT"

if [ -z "$CATALINA_TMPDIR" ] ; then
  # Define the java.io.tmpdir to use for Catalina
  CATALINA_TMPDIR="$CATALINA_BASE"/temp
fi

# Add tomcat-juli.jar to classpath
# tomcat-juli.jar can be over-ridden per instance
if [ -r "$CATALINA_BASE/bin/tomcat-juli.jar" ] ; then
  CLASSPATH=$CLASSPATH:$CATALINA_BASE/bin/tomcat-juli.jar
else
  CLASSPATH=$CLASSPATH:$CATALINA_HOME/bin/tomcat-juli.jar
fi

# Bugzilla 37848: When no TTY is available, don't output to console
have_tty=0
if [ "`tty`" != "not a tty" ]; then
    have_tty=1
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
  JAVA_HOME=`cygpath --absolute --windows "$JAVA_HOME"`
  JRE_HOME=`cygpath --absolute --windows "$JRE_HOME"`
  CATALINA_HOME=`cygpath --absolute --windows "$CATALINA_HOME"`
  CATALINA_BASE=`cygpath --absolute --windows "$CATALINA_BASE"`
  CATALINA_TMPDIR=`cygpath --absolute --windows "$CATALINA_TMPDIR"`
  CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
  JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"`
fi

# Set juli LogManager config file if it is present and an override has not been issued
if [ -z "$LOGGING_CONFIG" ]; then
  if [ -r "$CATALINA_BASE"/conf/logging.properties ]; then
    LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties"
  else
    # Bugzilla 45585
    LOGGING_CONFIG="-Dnop"
  fi
fi

if [ -z "$LOGGING_MANAGER" ]; then
  LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
fi

# Uncomment the following line to make the umask available when using the
# org.apache.catalina.security.SecurityListener
#JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.security.SecurityListener.UMASK=`umask`"

# ----- Execute The Requested Command -----------------------------------------

# Bugzilla 37848: only output this if we have a TTY
if [ $have_tty -eq 1 ]; then
  echo "Using CATALINA_BASE:   $CATALINA_BASE"
  echo "Using CATALINA_HOME:   $CATALINA_HOME"
  echo "Using CATALINA_TMPDIR: $CATALINA_TMPDIR"
  if [ "$1" = "debug" ] ; then
    echo "Using JAVA_HOME:       $JAVA_HOME"
  else
    echo "Using JRE_HOME:        $JRE_HOME"
  fi
  echo "Using CLASSPATH:       $CLASSPATH"
  if [ ! -z "$CATALINA_PID" ]; then
    echo "Using CATALINA_PID:    $CATALINA_PID"
  fi
fi

if [ "$1" = "jpda" ] ; then
  if [ -z "$JPDA_TRANSPORT" ]; then
    JPDA_TRANSPORT="dt_socket"
  fi
  if [ -z "$JPDA_ADDRESS" ]; then
    JPDA_ADDRESS="8000"
  fi
  if [ -z "$JPDA_SUSPEND" ]; then
    JPDA_SUSPEND="n"
  fi
  if [ -z "$JPDA_OPTS" ]; then
    JPDA_OPTS="-agentlib:jdwp=transport=$JPDA_TRANSPORT,address=$JPDA_ADDRESS,server=y,suspend=$JPDA_SUSPEND"
  fi
  CATALINA_OPTS="$JPDA_OPTS $CATALINA_OPTS"
  shift
fi

if [ "$1" = "debug" ] ; then
  if $os400; then
    echo "Debug command not available on OS400"
    exit 1
  else
    shift
    if [ "$1" = "-security" ] ; then
      if [ $have_tty -eq 1 ]; then
        echo "Using Security Manager"
      fi
      shift
      exec "$_RUNJDB" "$LOGGING_CONFIG" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
        -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \
        -sourcepath "$CATALINA_HOME"/../../java \
        -Djava.security.manager \
        -Djava.security.policy=="$CATALINA_BASE"/conf/catalina.policy \
        -Dcatalina.base="$CATALINA_BASE" \
        -Dcatalina.home="$CATALINA_HOME" \
        -Djava.io.tmpdir="$CATALINA_TMPDIR" \
        org.apache.catalina.startup.Bootstrap "$@" start
    else
      exec "$_RUNJDB" "$LOGGING_CONFIG" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
        -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \
        -sourcepath "$CATALINA_HOME"/../../java \
        -Dcatalina.base="$CATALINA_BASE" \
        -Dcatalina.home="$CATALINA_HOME" \
        -Djava.io.tmpdir="$CATALINA_TMPDIR" \
        org.apache.catalina.startup.Bootstrap "$@" start
    fi
  fi

elif [ "$1" = "run" ]; then

  shift
  if [ "$1" = "-security" ] ; then
    if [ $have_tty -eq 1 ]; then
      echo "Using Security Manager"
    fi
    shift
    eval exec "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
      -Djava.security.manager \
      -Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap "$@" start
  else
    eval exec "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $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
  fi

elif [ "$1" = "start" ] ; then

  if [ ! -z "$CATALINA_PID" ]; then
    if [ -f "$CATALINA_PID" ]; then
      if [ -s "$CATALINA_PID" ]; then
        echo "Existing PID file found during start."
        if [ -r "$CATALINA_PID" ]; then
          PID=`cat "$CATALINA_PID"`
          ps -p $PID >/dev/null 2>&1
          if [ $? -eq 0 ] ; then
            echo "Tomcat appears to still be running with PID $PID. Start aborted."
            echo "If the following process is not a Tomcat process, remove the PID file and try again:"
            ps -f -p $PID
            exit 1
          else
            echo "Removing/clearing stale PID file."
            rm -f "$CATALINA_PID" >/dev/null 2>&1
            if [ $? != 0 ]; then
              if [ -w "$CATALINA_PID" ]; then
                cat /dev/null > "$CATALINA_PID"
              else
                echo "Unable to remove or clear stale PID file. Start aborted."
                exit 1
              fi
            fi
          fi
        else
          echo "Unable to read PID file. Start aborted."
          exit 1
        fi
      else
        rm -f "$CATALINA_PID" >/dev/null 2>&1
        if [ $? != 0 ]; then
          if [ ! -w "$CATALINA_PID" ]; then
            echo "Unable to remove or write to empty PID file. Start aborted."
            exit 1
          fi
        fi
      fi
    fi
  fi

  shift
  #touch "$CATALINA_OUT"
  if [ "$1" = "-security" ] ; then
    if [ $have_tty -eq 1 ]; then
      echo "Using Security Manager"
    fi
    shift
    eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
      -Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
      -Djava.security.manager \
      -Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      org.apache.catalina.startup.Bootstrap "$@" start 2>&1 \
      "| /usr/local/sbin/cronolog" "$CATALINA_OUT" >> /dev/null "&"

  else
    eval "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $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 2>&1 \
      "| /usr/local/sbin/cronolog" "$CATALINA_OUT" >> /dev/null "&"

  fi

  if [ ! -z "$CATALINA_PID" ]; then
    echo $! > "$CATALINA_PID"
  fi

  echo "Tomcat started."

elif [ "$1" = "stop" ] ; then

  shift

  SLEEP=5
  if [ ! -z "$1" ]; then
    echo $1 | grep "[^0-9]" >/dev/null 2>&1
    if [ $? -gt 0 ]; then
      SLEEP=$1
      shift
    fi
  fi

  FORCE=0
  if [ "$1" = "-force" ]; then
    shift
    FORCE=1
  fi

  if [ ! -z "$CATALINA_PID" ]; then
    if [ -f "$CATALINA_PID" ]; then
      if [ -s "$CATALINA_PID" ]; then
        kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1
        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

  eval "\"$_RUNJAVA\"" $LOGGING_MANAGER $JAVA_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 "$@" stop

  # stop failed. Shutdown port disabled? Try a normal kill.
  if [ $? != 0 ]; then
    if [ ! -z "$CATALINA_PID" ]; then
      echo "The stop command failed. Attempting to signal the process to stop through OS signal."
      kill -15 `cat "$CATALINA_PID"` >/dev/null 2>&1
    fi
  fi

  if [ ! -z "$CATALINA_PID" ]; then
    if [ -f "$CATALINA_PID" ]; then
      while [ $SLEEP -ge 0 ]; do
        kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1
        if [ $? -gt 0 ]; then
          rm -f "$CATALINA_PID" >/dev/null 2>&1
          if [ $? != 0 ]; then
            if [ -w "$CATALINA_PID" ]; then
              cat /dev/null > "$CATALINA_PID"
              # If Tomcat has stopped don't try and force a stop with an empty PID file
              FORCE=0
            else
              echo "The PID file could not be removed or cleared."
            fi
          fi
          echo "Tomcat stopped."
          break
        fi
        if [ $SLEEP -gt 0 ]; then
          sleep 1
        fi
        if [ $SLEEP -eq 0 ]; then
          echo "Tomcat did not stop in time."
          if [ $FORCE -eq 0 ]; then
            echo "PID file was not removed."
          fi
          echo "To aid diagnostics a thread dump has been written to standard out."
          kill -3 `cat "$CATALINA_PID"`
        fi
        SLEEP=`expr $SLEEP - 1 `
      done
    fi
  fi

  KILL_SLEEP_INTERVAL=5
  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
        while [ $KILL_SLEEP_INTERVAL -ge 0 ]; do
            kill -0 `cat "$CATALINA_PID"` >/dev/null 2>&1
            if [ $? -gt 0 ]; then
                rm -f "$CATALINA_PID" >/dev/null 2>&1
                if [ $? != 0 ]; then
                    if [ -w "$CATALINA_PID" ]; then
                        cat /dev/null > "$CATALINA_PID"
                    else
                        echo "The PID file could not be removed."
                    fi
                fi
                echo "The Tomcat process has been killed."
                break
            fi
            if [ $KILL_SLEEP_INTERVAL -gt 0 ]; then
                sleep 1
            fi
            KILL_SLEEP_INTERVAL=`expr $KILL_SLEEP_INTERVAL - 1 `
        done
        if [ $KILL_SLEEP_INTERVAL -lt 0 ]; then
            echo "Tomcat has not been killed completely yet. The process might be waiting on some system call or might be UNINTERRUPTIBLE."
        fi
      fi
    fi
  fi

elif [ "$1" = "configtest" ] ; then

    eval "\"$_RUNJAVA\"" $LOGGING_MANAGER $JAVA_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 configtest
    result=$?
    if [ $result -ne 0 ]; then
        echo "Configuration error detected!"
    fi
    exit $result

elif [ "$1" = "version" ] ; then

    "$_RUNJAVA"   \
      -classpath "$CATALINA_HOME/lib/catalina.jar" \
      org.apache.catalina.util.ServerInfo

else

  echo "Usage: catalina.sh ( commands ... )"
  echo "commands:"
  if $os400; then
    echo "  debug             Start Catalina in a debugger (not available on OS400)"
    echo "  debug -security   Debug Catalina with a security manager (not available on OS400)"
  else
    echo "  debug             Start Catalina in a debugger"
    echo "  debug -security   Debug Catalina with a security manager"
  fi
  echo "  jpda start        Start Catalina under JPDA debugger"
  echo "  run               Start Catalina in the current window"
  echo "  run -security     Start in the current window with security manager"
  echo "  start             Start Catalina in a separate window"
  echo "  start -security   Start in a separate window with security manager"
  echo "  stop              Stop Catalina, waiting up to 5 seconds for the process to end"
  echo "  stop n            Stop Catalina, waiting up to n seconds for the process to end"
  echo "  stop -force       Stop Catalina, wait up to 5 seconds and then use kill -KILL if still running"
  echo "  stop n -force     Stop Catalina, wait up to n seconds and then use kill -KILL if still running"
  echo "  configtest        Run a basic syntax check on server.xml - check exit code for result"
  echo "  version           What version of tomcat are you running?"
  echo "Note: Waiting for the process to end and use of the -force option require that \$CATALINA_PID is defined"
  exit 1

fi