Dobrev.EU Blog

Things I want to share

Install Tomcat 7, Redis 2.6, MySQL Server on CentOS

| Comments

Overview

This post will cover installing and basic configuration of Tomcat 7 on CentOS 5.x. or CentOS 6.x. David Ghedini already covered most of the installation process for JDK 1.7, Tomcat 7 etc. but I’m including the installation and basic configuration of Redis 2.6.11.

Tomcat 7 implements the JavaServer Pages 2.2 and Servlet 3.0 specifications and a number of new features. The Manager application also has a new look and finer-grain roles and access than 6.x. In this post, we’ll install Tomcat 7, the new JDK 7, configure Tomcat as a service, create a start/stop script, and (optionally) configure Tomcat to run under a non-root user. We will also configure basic access to Tomcat Manager and take a quick look at memory management using JAVA_OPTS. Finally, we will look at running Tomcat on port 80 as well as some strategies for running Tomcat behind Apache. At the time of writing this post Tomcat 7.0.39 is the latest stable release of Tomcat 7. If you are using a different release, simply change the file names below accordingly.

Installation

Java Development Kit 7 update 17

To begin, we’ll need to install the Java Development Kit (JDK) 7. JDK 1.6 is the minimum JDK version for Tomcat 7.

You can download the latest JDK here: We’ll install the latest JDK, which is JDK 7, Update 17. The JDK is specific to 32 and 64 bit versions. My CentOS box is 64 bit, so I’ll need: jdk-7u17-linux-x64.tar.gz. If you are on 32 bit, you’ll need: jdk-7u17-linux-i586.tar.gz

Start by creating a new directory /opt/java:

1
2
mkdir -p /opt/java
cd /opt/java

Download the latest JDK and extract it to the folder we created above:

1
tar -xzpf jdk-7u17-linux-x64.tar.gz

This will create a folder jdk1.7.0_17. This is going to be our JAVA_HOME. Now change to /etc/profile.d and create a file inside, for example java.sh with following information inside:

/etc/profile.d/java.sh
1
2
export JAVA_HOME=/opt/java/jdk1.7.0_17
pathmunge ${JAVA_HOME}/bin after

and source /etc/profile for the changes to be applied:

Reloadlink
1
. /etc/profile

If you’re successful the output of the set command will show JAVA_HOME and an entry in the PATH variable too.

1
2
3
4
...
JAVA_HOME=/opt/java/jdk1.7.0_17
PATH=<snip>:/opt/java/jdk1.7.0_17/bin
...

Tomcat 7

Start by creating a new directory /opt/tomcat:

1
2
3
mkdir -p /opt/tomcat
mkdir -p /var/log/tomcat7
cd /opt/tomcat

Download apache-tomcat-7.0.37.tar.gz (or the latest version) here, save it to /opt/tomcat and extract the archive.

1
tar -xzf apache-tomcat-7.0.37.tar.gz

Tomcat 7 init.d script

Recent CentOS versions is already offering a startup script for Tomcat but as we install it from source we need to create these files for us. Start with creating /etc/init.d/tomcat7

/etc/init.d/tomcat7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#!/bin/bash
#
# tomcat6      This shell script takes care of starting and stopping Tomcat
#
# chkconfig: - 80 20
#
### BEGIN INIT INFO
# Provides: tomcat7
# Required-Start: $network $syslog
# Required-Stop: $network $syslog
# Default-Start:
# Default-Stop:
# Description: Release implementation for Servlet 2.5 and JSP 2.1
# Short-Description: start and stop tomcat
### END INIT INFO
#
# - originally written by Henri Gomez, Keith Irwin, and Nicolas Mailhot
# - heavily rewritten by Deepak Bhole and Jason Corley
# - modified by Martin Dobrev
#

## Source function library.
#. /etc/rc.d/init.d/functions
# Source LSB function library.
if [ -r /lib/lsb/init-functions ]; then
    . /lib/lsb/init-functions
else
    exit 1
fi

DISTRIB_ID=`lsb_release -i -s 2>/dev/null`

NAME="$(basename $0)"
unset ISBOOT
if [ "${NAME:0:1}" = "S" -o "${NAME:0:1}" = "K" ]; then
    NAME="${NAME:3}"
    ISBOOT="1"
fi

# For SELinux we need to use 'runuser' not 'su'
if [ -x "/sbin/runuser" ]; then
    SU="/sbin/runuser -s /bin/sh"
else
    SU="/bin/su -s /bin/sh"
fi

# Get the tomcat config (use this for environment specific settings)
TOMCAT_CFG="/etc/tomcat7/tomcat7.conf"
if [ -r "$TOMCAT_CFG" ]; then
    . $TOMCAT_CFG
fi

# Get instance specific config file
if [ -r "/etc/sysconfig/${NAME}" ]; then
    . /etc/sysconfig/${NAME}
fi

# Define which connector port to use
CONNECTOR_PORT="${CONNECTOR_PORT:-8080}"

# Path to the tomcat launch script
TOMCAT_SCRIPT="/opt/tomcat/apache-tomcat-7.0.37/bin/catalina.sh"

# Tomcat program name
TOMCAT_PROG="${NAME}"

# Define the tomcat username
TOMCAT_USER="${TOMCAT_USER:-tomcat}"

# Define the tomcat log file
TOMCAT_LOG="${TOMCAT_LOG:-/var/log/tomcat7/${NAME}-initd.log}"

RETVAL="0"

function parseOptions() {
    options=""
    #options="$options $(
    #             awk '!/^#/ && !/^$/ { ORS=" "; print "export ", $0, ";" }' \
    #             $TOMCAT_CFG
    #         )"
    if [ -r "/etc/sysconfig/${NAME}" ]; then
        options="$options $(
                     awk '!/^#/ && !/^$/ { ORS=" ";
                                           print "export ", $0, ";" }' \
                     /etc/sysconfig/${NAME}
                 )"
    fi
    TOMCAT_SCRIPT="$options ${TOMCAT_SCRIPT}"
}

# rhbz 757632
function version() {
        parseOptions
        $SU - $TOMCAT_USER -c "${TOMCAT_SCRIPT} version" >> ${TOMCAT_LOG} 2>&1 || RETVAL="4"
}

# See how we were called.
function start() {

   echo -n "Starting ${TOMCAT_PROG}: "
   if [ "$RETVAL" != "0" ]; then
     log_failure_msg
     return
   fi
   if [ -f "/var/lock/subsys/${NAME}" ]; then
        if [ -f "/var/run/${NAME}.pid" ]; then
            read kpid < /var/run/${NAME}.pid
#           if checkpid $kpid 2>&1; then
            if [ -d "/proc/${kpid}" ]; then
                log_success_msg
                if [ "$DISTRIB_ID" = "MandrivaLinux" ]; then
                    echo
                fi
                RETVAL="0"
                return
            fi
        fi
    fi
    # fix permissions on the log and pid files
    export CATALINA_PID="/var/run/${NAME}.pid"
    touch $CATALINA_PID 2>&1 || RETVAL="4"
    if [ "$RETVAL" -eq "0" -a "$?" -eq "0" ]; then
      chown ${TOMCAT_USER}:${TOMCAT_USER} $CATALINA_PID
    fi
    [ "$RETVAL" -eq "0" ] && touch $TOMCAT_LOG 2>&1 || RETVAL="4"
    if [ "$RETVAL" -eq "0" -a "$?" -eq "0" ]; then
      chown ${TOMCAT_USER}:${TOMCAT_USER} $TOMCAT_LOG
    fi
    parseOptions
    if [ "$RETVAL" -eq "0" -a "$SECURITY_MANAGER" = "true" ]; then
        $SU - $TOMCAT_USER -c "${TOMCAT_SCRIPT} start-security" \
            >> ${TOMCAT_LOG} 2>&1 || RETVAL="4"
    else

       [ "$RETVAL" -eq "0" ] && $SU - $TOMCAT_USER -c "${TOMCAT_SCRIPT} start" >> ${TOMCAT_LOG} 2>&1 || RETVAL="4"
    fi
    if [ "$RETVAL" -eq "0" ]; then
        log_success_msg
        touch /var/lock/subsys/${NAME}
    else
        log_failure_msg "Error code ${RETVAL}"
    fi
    if [ "$DISTRIB_ID" = "MandrivaLinux" ]; then
        echo
    fi
}

function stop() {
    echo -n "Stopping ${TOMCAT_PROG}: "
    if [ -f "/var/lock/subsys/${NAME}" ]; then
      parseOptions
      if [ "$RETVAL" -eq "0" ]; then
         touch /var/lock/subsys/${NAME} 2>&1 || RETVAL="4"
         [ "$RETVAL" -eq "0" ] && $SU - $TOMCAT_USER -c "${TOMCAT_SCRIPT} stop" >> ${TOMCAT_LOG} 2>&1 || RETVAL="4"
      fi
      if [ "$RETVAL" -eq "0" ]; then
         count="0"
         if [ -f "/var/run/${NAME}.pid" ]; then
            read kpid < /var/run/${NAME}.pid
            until [ "$(ps --pid $kpid | grep -c $kpid)" -eq "0" ] || \
                      [ "$count" -gt "$SHUTDOWN_WAIT" ]; do
                    if [ "$SHUTDOWN_VERBOSE" = "true" ]; then
                        echo "waiting for processes $kpid to exit"
                    fi
                    sleep 1
                    let count="${count}+1"
                done
                if [ "$count" -gt "$SHUTDOWN_WAIT" ]; then
                    if [ "$SHUTDOWN_VERBOSE" = "true" ]; then
                        log_warning_msg "killing processes which did not stop after ${SHUTDOWN_WAIT} seconds"
                    fi
                    kill -9 $kpid
                fi
                log_success_msg
            fi
            rm -f /var/lock/subsys/${NAME} /var/run/${NAME}.pid
        else
            log_failure_msg
            RETVAL="4"
        fi
    else
        log_success_msg
        RETVAL="0"
    fi
    if [ "$DISTRIB_ID" = "MandrivaLinux" ]; then
        echo
    fi
}

function status()
{
   checkpidfile
   if [ "$RETVAL" -eq "0" ]; then
      log_success_msg "${NAME} (pid ${kpid}) is running..."
   elif [ "$RETVAL" -eq "1" ]; then
      log_failure_msg "PID file exists, but process is not running"
   else
      checklockfile
      if [ "$RETVAL" -eq "2" ]; then
         log_failure_msg "${NAME} lockfile exists but process is not running"
      else
         pid="$(/usr/bin/pgrep -d , -u ${TOMCAT_USER} -G ${TOMCAT_USER} java)"
         if [ -z "$pid" ]; then
             log_success_msg "${NAME} is stopped"
             RETVAL="3"
         else
             log_success_msg "${NAME} (pid $pid) is running..."
             RETVAL="0"
         fi
      fi
  fi
}

function checklockfile()
{
   if [ -f /var/lock/subsys/${NAME} ]; then
      pid="$(/usr/bin/pgrep -d , -u ${TOMCAT_USER} -G ${TOMCAT_USER} java)"
# The lockfile exists but the process is not running
      if [ -z "$pid" ]; then
         RETVAL="2"
      fi
   fi
}
function checkpidfile()
{
   if [ -f "/var/run/${NAME}.pid" ]; then
      read kpid < /var/run/${NAME}.pid
      if [ -d "/proc/${kpid}" ]; then
# The pid file exists and the process is running
          RETVAL="0"
      else
# The pid file exists but the process is not running
         RETVAL="1"
         return
      fi
   fi
# pid file does not exist and program is not running
   RETVAL="3"
}

function usage()
{
   echo "Usage: $0 {start|stop|restart|condrestart|try-restart|reload|force-reload|status|version}"
   RETVAL="2"
}

# See how we were called.
RETVAL="0"
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    condrestart|try-restart)
        if [ -f "/var/run/${NAME}.pid" ]; then
            stop
            start
        fi
        ;;
    reload)
        RETVAL="3"
        ;;
    force-reload)
        if [ -f "/var/run/${NAME}.pid" ]; then
            stop
            start
        fi
        ;;
    status)
        status
        ;;
    version)
                version
#        ${TOMCAT_SCRIPT} version
        ;;
    *)
      usage
      ;;
esac

exit $RETVAL

This script is reading it’s configuration from /etc/sysconfig/tomcat7:

/etc/sysconfig/tomcat7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# Service-specific configuration file for tomcat7. This will be sourced by
# the SysV init script thus allowing values to be overridden in
# a per-service manner.
#
#
# To change values for a specific service make your edits here.
# To create a new service create a link from /etc/init.d/<your new service> to
# /etc/init.d/tomcat7 (do not copy the init script) and make a copy of the
# /etc/sysconfig/tomcat7 file to /etc/sysconfig/<your new service> and change
# the property values so the two services won't conflict. Register the new
# service in the system as usual (see chkconfig and similars).
#

# Where your java installation lives
#JAVA_HOME="/usr/lib/jvm/java"

# Where your tomcat installation lives
CATALINA_BASE="/opt/tomcat/apache-tomcat-7.0.37"
CATALINA_HOME="/opt/tomcat/apache-tomcat-7.0.37"
JASPER_HOME="/opt/tomcat/apache-tomcat-7.0.37"
CATALINA_TMPDIR="/opt/tomcat/apache-tomcat-7.0.37/temp"

# You can pass some parameters to java here if you wish to
#JAVA_OPTS="-Xminf0.1 -Xmaxf0.3"

# Use JAVA_OPTS to set java.library.path for libtcnative.so
#JAVA_OPTS="-Djava.library.path=/usr/lib"

# What user should run tomcat
TOMCAT_USER="root"

# You can change your tomcat locale here
LANG="en_US"

# Run tomcat under the Java Security Manager
SECURITY_MANAGER="false"

# Time to wait in seconds, before killing process
SHUTDOWN_WAIT="5"

# Whether to annoy the user with "attempting to shut down" messages or not
SHUTDOWN_VERBOSE="false"

# Set the TOMCAT_PID location
CATALINA_PID="/var/run/tomcat7.pid"

# Connector port is 8080 for this tomcat6 instance
#CONNECTOR_PORT="8080"

# If you wish to further customize your tomcat environment,
# put your own definitions here
# (i.e. LD_LIBRARY_PATH for some jdbc drivers)

Then enable the service to make sure it’s being automatically started on system boot:

Start tomcat7 on boot
1
2
3
chkconfig --add tomcat7
chkconfig --level 2345 tomcat7 on
service tomcat7 start

Running Tomcat 7 as non-privileged user

If you want to start Tomcat as a non-privileged user then change the ownership of the Tomcat folder. On my systems I’m creating the tomcat user and group:

Running Tomcat 7 as non-privileged user
1
2
3
groupadd tomcat
useradd -g tomcat -m -s /bin/bash -d /opt/tomcat tomcat
chown tomcat:tomcat /opt/tomcat/apache-tomcat-7.0.37

Then change TOMCAT_USER in /etc/sysconfig/tomcat7 and restart the service after that. Congratulations! You already have your Tomcat instance running as non-privileged user.

Running multiple Tomcat instances on the same server

You can read the [[How to run multiple instances of Tomcat on a single server]] article and adapt to your needs.

Redis 2.6.11

Start by creating a new directory /opt/redis:

1
2
mkdir -p /opt/redis
cd /opt/redis

Download Redis from here.

1
2
3
4
wget http://redis.googlecode.com/files/redis-2.6.11.tar.gz
tar xzf redis-2.6.11.tar.gz
cd redis-2.6.11
make

If you get any errors please make sure you have “Development Tools” installed on your server. If you get error that a new version of jmalloc is needed then compile with the following command:

1
make MALLOC=libc

You can skip make test because it needs TCL 8.5 and in CentOS 5 you need to compile it from source.

Install Redis in the folder you created above and copy redis.conf:

1
2
make PREFIX=/opt/redis install
cp redis.conf /opt/redis

Redis init.d script

Start with creating /etc/init.d/redis-server:

/etc/init.d/redis-server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/bin/sh
#
# redis-server - this script starts and stops the redis-server daemon
#
# chkconfig:   - 85 15
# description:  Redis is a persistent key-value database
# processname: redis-server
# config:      /etc/redis/redis.conf
# config:      /etc/sysconfig/redis
# pidfile:     /var/run/redis.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

redis="/opt/redis/bin/redis-server"
prog=$(basename $redis)

REDIS_CONF_FILE="/opt/redis/redis.conf"

[ -f /etc/sysconfig/redis ] && . /etc/sysconfig/redis

lockfile=/var/lock/subsys/redis-server

start() {
    [ -x $redis ] || exit 5
    [ -f $REDIS_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $redis $REDIS_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -15
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    echo -n $"Reloading $prog: "
    killproc $redis -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac

Then enable the service to make sure it’s being automatically started on system boot:

Start Redis server on boot
1
2
3
chkconfig --add redis-server
chkconfig --level 2345 redis-server on
service redis-server start

MySQL

Depending on the MySQL version you intend to use there are a plenty of options you can use for this. But as my DB projects don’t require any particular MySQL version I’m using the MySQL server from yum:

1
yum -y install mysql mysql-server

Then start the service and secure your installation following the onscreen instructions:

1
2
service mysqld start
mysql_secure_installation

Then enable the service to make sure it’s being automatically started on system boot:

1
2
chkconfig --add mysqld
chkconfig --level 2345 mysqld on

Comments