Install Jenkins on CentOS as a Service

Updated post: Yum Install Jenkins as a Service on CentOS 7. You probably want to do it this way, it’s much easier. Just saying.

This guide describes how to install Jenkins on your CentOS server as an init.d service. Jenkins is a great continuous integration server that can do a lot of cool automation, but I won’t go into all of those details here. If you don’t have Java or ANT, you should install them before getting started – I am usingĀ java-1.7.0-openjdk.x86_64 but choose the appropriate JVM for your server, either the OpenJDK or Oracle JVM is required.

yum -y install java-1.7.0-openjdk.x86_64 ant

Install Jenkins with CentOS Configuration

Now on to the actual setup. All of the uppercase variables in the text below can be set in the /etc/sysconfig/jenkins file. There are defaults for all values, so only create this file if you want to override them for your own environment. First let’s create the JENKINS_USER.

groupadd jenkins
useradd -g jenkins jenkins

Next create your JENKINS_HOME and install Jenkins by downloading the latest version of the jenkins.war.

sudo mkdir -p /usr/local/jenkins
cd /usr/local/jenkins
wget http://mirrors.jenkins-ci.org/war/latest/jenkins.war

Now create the scripts to start and stop the process, called /usr/local/start-jenkins.sh and /usr/local/stop-jenkins.sh respectively. Both of these files should be in the JENKINS_HOME.

/usr/local/jenkins/start-jenkins.sh

#!/bin/bash

# import sysconfig settings and set defaults
[ -f /etc/sysconfig/jenkins ] && . /etc/sysconfig/jenkins
[ "${JENKINS_HOME}" == "" ] &&
	JENKINS_HOME=/usr/local/jenkins
[ "${JENKINS_LOG}" == "" ] &&
	JENKINS_LOG=/home/jenkins/jenkins.log
[ "${JENKINS_JAVA}" == "" ] &&
	JENKINS_JAVA=/usr/bin/java
[ "${JENKINS_JAVAOPTS}" == "" ] &&
	JENKINS_JAVAOPTS=""
[ "${JENKINS_IP}" == "" ] &&
	JENKINS_IP=0.0.0.0
[ "${JENKINS_PORT}" == "" ] &&
	JENKINS_PORT=8080
[ "${JENKINS_ARGS}" == "" ] &&
	JENKINS_ARGS=""

JENKINS_WAR=${JENKINS_HOME}/jenkins.war

# check for config errors
JENKINS_ERRORS=()
[ ! -f ${JENKINS_WAR} ] &&
	JENKINS_ERRORS[${#JENKINS_ERRORS[*]}]="JENKINS_HOME	: The jenkins.war could not be found at ${JENKINS_HOME}/jenkins.war"
[ ! -f $JENKINS_JAVA ] &&
	JENKINS_ERRORS[${#JENKINS_ERRORS[*]}]="JENKINS_JAVA	: The java executable could not be found at $JENKINS_JAVA"

# display errors if there are any, otherwise start the process
if [ ${#JENKINS_ERRORS[*]} != '0' ]
then
	echo "CONFIGURATION ERROR:"
	echo "    The following errors occurred when starting Jenkins."
	echo "    Please set the appropriate values at /etc/sysconfig/jenkins"
	echo ""
	for (( i=0; i<${#JENKINS_ERRORS[*]}; i++ ))
	do
		echo "${JENKINS_ERRORS[${i}]}"
	done
	echo ""
	exit 1
else
	echo "starting service"
	echo "nohup nice $JENKINS_JAVA $JENKINS_JAVAOPTS -jar $JENKINS_WAR --httpListenAddress=$JENKINS_IP --httpPort=$JENKINS_PORT $> $JENKINS_LOG 2>&1 &"
	nohup nice $JENKINS_JAVA $JENKINS_JAVAOPTS -jar $JENKINS_WAR --httpListenAddress=$JENKINS_IP --httpPort=$JENKINS_PORT $> $JENKINS_LOG 2>&1 &
fi

/usr/local/jenkins/stop-jenkins.sh

#!/bin/bash
kill `ps -ef | grep [j]enkins.war | awk '{ print $2 }'`

Now create a script called /etc/init.d/jenkins to allow the server to be started and stopped as a service.

/etc/init.d/jenkins

#! /bin/bash
# chkconfig: 2345 90 10
# description: Jenkins Continuous Integration server
# processname: /usr/local/jenkins/jenkins.war

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

# Get network sysconfig.
. /etc/sysconfig/network

# Check that networking is up, otherwise we can't start
[ "${NETWORKING}" = "no" ] && exit 0

# Get the Jenkins sysconfig
[ -f /etc/sysconfig/jenkins ] && . /etc/sysconfig/jenkins
[ "${JENKINS_HOME}" = "" ] &&
	JENKINS_HOME=/usr/local/jenkins
[ "${JENKINS_USER}" == "" ] &&
	JENKINS_USER=jenkins

startup=${JENKINS_HOME}/start-jenkins.sh
shutdown=${JENKINS_HOME}/stop-jenkins.sh
export JAVA_HOME=/usr/local/java/

start(){
	echo -n $"Starting Jenkins service: "
	pid=`ps -ef | grep [j]enkins.war | wc -l`
	if [ $pid -gt 0 ]; then
		echo "Jenkins is already running"
		exit 1
	fi
	su - $JENKINS_USER -c $startup
	RETVAL=$?
	[ $RETVAL == 0 ] &&
		echo "Jenkins was started successfully." ||
		echo "There was an error starting Jenkins."
}

stop(){
	action $"Stopping Jenkins service: "
	pid=`ps -ef | grep [j]enkins.war | wc -l`
	if [ ! $pid -gt 0 ]; then
		echo "Jenkins is not running"
		exit 1
	fi
	su - $JENKINS_USER -c $shutdown
	RETVAL=$?
	[ $RETVAL == 0 ] &&
		echo "Jenkins was stopped successfully." ||
		echo "There was an error stopping Jenkins."
}

status(){
	pid=`ps -ef | grep [j]enkins.war | wc -l`
	if [ $pid -gt 0 ]; then
 		echo "Jenkins is running..."
 	else
 		echo "Jenkins is stopped..."
	fi
}

restart(){
 	stop
 	sleep 5
 	start
}

# Call functions as determined by args.
case "$1" in
start)
	start;;
stop)
	stop;;
status)
	status;;
restart)
	restart;;
*)
	echo $"Usage: $0 {start|stop|status|restart}"
	exit 1
esac

exit 0

Make sure that the JENKINS_USER is the owner of the JENKINS_HOME directory and scripts, and that the scripts have executable flags set.

chown -R jenkins. /usr/local/jenkins
chmod a+x /usr/local/jenkins/start-jenkins.sh
chmod a+x /usr/local/jenkins/stop-jenkins.sh
chmod a+x /etc/init.d/jenkins

You can then start, stop, restart, and check the status of the service via the following commands, or control if it is launched on boot using chkconfig:

service jenkins status
service jenkins start
service jenkins restart
service jenkins stop
chkconfig jenkins on

The additional variables that can be set at /etc/sysconfig/jenkins and their defaults are as follows:

# Jenkins system configuration
JENKINS_HOME=/usr/local/jenkins
JENKINS_USER=jenkins
JENKINS_LOG=/home/jenkins/jenkins.log
JENKINS_JAVA=/usr/bin/java
JENKINS_JAVAOPTS=""
JENKINS_IP=0.0.0.0
JENKINS_PORT=8080
JENKINS_ARGS=""

Since my development server already has Apache running on it, the easiest way to expose the application to the world was via a reverse proxy after I installed Jenkins. The VirtualHost for this subdomain ends up looking like the following:

<VirtualHost *:80>
        ServerName jenkins.doublesharp.com
        DocumentRoot    /var/www/html

        ProxyPass / http://localhost:8080/ nocanon
        ProxyPassReverse / http://localhost:8080/
        ProxyRequests Off
        ProxyPreserveHost On
        <Proxy http://localhost:8080/*>
                Order deny,allow
                Allow from all
        </Proxy>
        # If using reverse proxy from SSL
        #Header edit Location ^http: https:
</VirtualHost>

Complete the setup by restarting Apache.

service httpd restart

You may also like...

6 Responses

  1. Mateusz says:

    Nice tutorial!

    Keep in mind that instead of using:
    pid=`ps -ef | grep [j]enkins.war | wc -l`

    you should use
    pid=`ps -ef | grep [j]enkins.war | grep -v grep | wc -l`

    Thanks!

    • User Avatar Justin Silver says:

      I agree that it certainly won’t hurt to remove “grep” from the results, but I find that because the results of ps are being passed to grep that it doesn’t show up in the output. This is the output from my dev server:

      [root@dev1 ~]# ps -ef | grep [j]enkins.war
      jenkins  19352     1 44 14:32 ?        00:00:11 /usr/bin/java -jar /usr/local/jenkins/jenkins.war --httpListenAddress=0.0.0.0 --httpPort=8080 $
      
      • Mateusz says:

        Which server do you have? I never saw grep which doesn’t show it’s own process šŸ™‚

        • User Avatar Justin Silver says:

          Sorry, wasn’t really thinking when I replied before. I am running CentOS 5.10, and you are correct that grep will show up in the list of running processes. The reason that we don’t have to omit “grep” in this case though is because of the regular expression used for matching – “[j]enkins.war”. Using the square brackets on the first letter uses a character match on just that letter so that “[j]enkins” will match “jenkins” but “jenkins” won’t match “[j]enkins” (which is what shows up on the output from ps). If the square brackets are omitted then you would need to include grep -v grep. Does that make sense?

Leave a Reply

Your email address will not be published. Required fields are marked *