Dashboard > CruiseControl > RunningCruiseControlFromUnixInit
RunningCruiseControlFromUnixInit Log In View a printable version of the current page.

Added by Robert Watkins , last edited by kevin quigley on Jan 31, 2007  (view change) show comment
Labels: 
(None)

Use a script similar to the following:

#!/bin/sh
#content of /opt/cruisecontrol/init script
# chkconfig: 345 99 05
# description: CruiseControl build loop (see /home/tools)

# CruiseControl Unix Startup Script Version 2.1
#
# based on http://confluence.public.thoughtworks.org/display/CC/UnixStartupScriptVersion1.x
# adapted for multiple projects
# also based on the file attached to the above page created by Jerome Lacoste

#
# CruiseControl startup: Startup and kill script for Cruise Control
#


###################################################################################################
# USER CONFIGURATION
#
# Fill in these values for your Cruise Control setup

# What user will Cruise Control run as?  The user will need permission to write and modify files
# in the next entries.
CC_USER=cruisecontrol


# Where is the CC startup script located?
CC_INSTALL_DIR=

# In what directory is the config.xml file located for CC?
# default: CC_WORK_DIR=$CC_INSTALL_DIR
CC_WORK_DIR=$CC_INSTALL_DIR

# Where will the cruisecontrol.log file be located?
# default: CC_LOGFILE_DIR=$CC_INSTALL_DIR
CC_LOGFILE_DIR=$CC_INSTALL_DIR


#######################
# ENVIRONMENT ADDITIONS

# Add environement variables here that are needed by your build.
# example:
#  export JAVA_HOME=/usr/local/java
#
# or like this for local variables ONLY used in this file:
#  JAVA_HOME=/usr/local/java


# Add path to additional executables needed for project build.  See PATH entry below for base config.
# No additional action taken when blank.
PATH_ADDITIONS=



##############################
# CRUISE CONTROL PORT SETTINGS

# Port for Jetty reporting application.  You can access it by going to http://localhost:8080
# default CC_WEBPORT=8080
CC_WEBPORT=8080

# JMX port for webapp and Java Management eXtensions (JMX).  You can access it by going to http://localhost:8080
# Change only if this port is in use as the webapp will also need modification.
# default CC_JMXPORT=8082
CC_JMXPORT=8082

# RMI port for control via Java's Remote Management Interface (RMI)
# Leave blank to disable.
CC_RMIPORT=



###################################################################################################
# DO NOT MODIFY ENTRIES BELOW THIS LINE

NAME=cruisecontrol
DESC="CruiseControl - continuous integration build loop"


PATH=/sbin:/usr/sbin:/usr/bin:/bin
# add additions if variable has text defined
if [ -n "$PATH_ADDITIONS" ]; then
    PATH=$PATH_ADDITIONS:$PATH
fi
export PATH


CC_DAEMON=$CC_INSTALL_DIR/cruisecontrol.sh

CC_CONFIG_FILE=$CC_WORK_DIR/config.xml

CC_LOG_FILE=$CC_LOGFILE_DIR/cruisecontrol.log

CC_COMMAND="$CC_DAEMON -configfile $CC_CONFIG_FILE -webport $CC_WEBPORT -jmxport $CC_JMXPORT -rmiport $CC_RMIPORT"

# overwrite settings from default file
if [ -f /etc/default/cruisecontrol ]; then
  . /etc/default/cruisecontrol
fi

# does the executable exist?
test -f $CC_DAEMON || (echo "The executable $CC_DAEMON does not exist!" && exit 0)

if [ `id -u` -ne 0 ]; then
        echo "Not starting/stopping $DESC, you are not root."
        exit 4
fi

# Get the PID output from the startup script
if [ -f $CC_INSTALL_DIR/cc.pid ]; then
	CC_PID=`cat $CC_INSTALL_DIR/cc.pid`
else
	echo "No cc.pid file found.  CC process may not be controllable from this script!"
fi


case "$1" in

  'start')
    cd $CC_INSTALL_DIR
    #echo "CC environtment at startup" > cc.startup.env
    #env >> cc.startup.env
    su $CC_USER -c "/bin/sh -c \"$CC_COMMAND >> $CC_LOG_FILE 2>&1\"" & RETVAL=$?
    echo "$NAME started with jmx on port ${CC_JMXPORT}"
    ;;

  'stop')
    if [ -n "$CC_PID" ] && ps -p ${CC_PID} > /dev/null ; then
     kill -9 ${CC_PID}
      $0 status
      RETVAL=$?
    else
      echo "$NAME is not running"
      RETVAL=1
    fi
    ;;

  'status')
    if [ -n "$CC_PID" ] && ps -p ${CC_PID} > /dev/null ; then
      echo $NAME \(pids $CC_PID\) is running
      RETVAL=0
    else
      echo "$NAME is stopped"
      RETVAL=1
    fi
    ;;

  'restart')
    $0 stop && $0 start
    RETVAL=$?
    ;;

  *)
    echo "Usage: $0 { start | stop | status | restart }"
    exit 1
    ;;
esac
#echo ending $0 $$....
exit 0;

changelog

Fixed stop command and status reporting by changing process control (PID use)
This relies on the following change to the last lines of the startup script, cruisecontrol.sh:

< exec $EXEC

> $EXEC &
> echo $! > cc.pid

-kevin quigley


Added feature for setting -webport command line option along with a few comments

-kevin quigley


Updated unix script to ensure CC_COMMAND would be run under a /bin/sh shell for the given CC_USER, regardless of that user's chosen shell.
Reorganized user configuration settings into easily identifiable blocks and added comments detailing what should be changed an how.
Added PATH supplementation so that the user doesn't have to touch the original PATH.

-kevin quigley


moved original script to UnixStartupScriptVersion1.x as a child of this page, along with Jerome's moca unix script which was great help in creating the one now posted here.

modified JMX script below to render better on the wiki page as "code" tags ignore wiki width formatting

-kevin quigley

Simple explanation of Linux-init

Put this script into /etc/init.d (or wherever your system holds init-style scripts). Add symlinks in each of your /etc/rc.* directories to it (On RedHat, use chkconfig). Your mileage may vary, depending on your OS and level of UNIX admin expertise.

start/stop daemon orders

You should be able to start the build loop before or after the reporting, without any particular issue.

Using JMX for Unix Init Scripts

The following script (based on the one above) has been slightly modified to use JMX for stopping CruiseControl and for getting the project status.
Additionally it provides an update mechanism, to update the config.xml for cruisecontrol from subversion (if needed). It should be noted, that the status information is fetched via greping the XML output of the JMX console (via template=identity). Currently there are used some standard unix commands (grep, cut, perl, curl) to extract the information from the XML. A better and more robust approach would be to use XML processing tools, like xsltproc or xmlstarlet but they might not be available on every server running CruiseControl.

/etc/init.d/cruisecontrol
#!/bin/sh
# chkconfig: 2345 95 05
# description: CruiseControl build loop
#
# based on http://confluence.public.thoughtworks.org/display/CC/RunningCruiseControlFromUnixInit
# adapted for JMX access
#
#
# Cruise Control startup: Startup and kill script for Cruise Control
#

PATH=/sbin:/usr/sbin:/usr/bin:/bin
export PATH

#CCUSER=cruise
CCUSER=root # FIXME: Create special user to run CC builds
# this script starts multiple cruisecontrol build loops

CCDIR=/opt/ewa-cc
CCSTARTSCRIPT=$CCDIR/cc.sh
JMXURL="http://localhost:8000"

# Activate the following, if you want parallel builds:
#CCARGS="-p"

# Get cruisecontrol status via JMX:
stat=`curl -s "$JMXURL/getattribute?objectname=CruiseControl%20Manager:id=unique&attribute=Projects&format=collection&template=identity" \
   | perl -pe 's/>/>\n/g' | grep '<Element ' | cut -d '"' -f 2`

# above was one line, broken to fit better on the wiki
# if it doesn't work as written, reappend the line starting with a pipe "|" to the one above. -quig


case "$1" in

    "start")
         # pass on the environment
         su $CCUSER -c $CCSTARTSCRIPT $CCARGS
         sleep 3
         $0 status
         RETVAL=$?
    ;;

    "stop")
        if [ "$stat" ]
        then
          curl -s "$JMXURL/invoke?operation=halt&objectname=CruiseControl+Manager:id=unique"
          $0 status
          RETVAL=$?
        else
          echo "cruisecontrol is not running"
          RETVAL=1
        fi
      ;;

  'status')
    if [ "$stat" ]
    then
      echo cruisecontrol is running:
      echo "$stat"
      RETVAL=0
    else
      echo "cruisecontrol is stopped"
      RETVAL=1
    fi
    ;;

  'restart')
    $0 stop && $0 start
    RETVAL=$?
    ;;

  'update')
    cd $CCDIR && svn up
    RETVAL=$?
    ;;

  *)
    echo "Usage: $0 { start | stop | status | restart | update }"
    exit 1
esac
exit 0;

The following script is a wrapper script, which allows the following:

  • Launch multiple instances in parallel
  • Configure common startup parameters independently of the CruiseControl distribution
/etc/init.d/cruisecontrol
#!/bin/sh
# run cruisecontrol for the various projects
# started by /etc/init.d/cruisecontrol which sets up the environment
# Originally taken from http://confluence.public.thoughtworks.org/display/CC/RunningCruiseControlFromUnixInit

CCDIR=/opt/ewa-cc
CCLOGS=$CCDIR/logs
CCPROJECTS=$CCDIR/projects
CCCONFIG=$CCDIR/config.xml
CCSTARTSCRIPT=$CCDIR/cruisecontrol.sh
CCWORKDIR=$CCLOGS
#CCDEBUG="-debug"
CCJMX="-port"
CCARGS="$CCDEBUG $CCJMX -configfile $CCCONFIG"
SLEEP=1
parallel=0

if [ "$1" == "-p" ]; then
	parallel=1
	shift
fi
PROJECTS=${@:-`( cd $CCPROJECTS && find -type d -mindepth 1 -maxdepth 1 | xargs -n 1 basename) | grep -v '\.svn'`}

cd $CCWORKDIR
if [ "$parallel" == "1" ]; then
	# Run one build loop per unit project
	for project in $PROJECTS; do
		if [ -d $CCPROJECTS/$project ]; then
			prjlogdir=$CCLOGS/$project
			mkdir -p $prjlogdir
			$CCSTARTSCRIPT $CCARGS -projectname $project > $prjlogdir/stdout.log 2>&1 &
			sleep $SLEEP
		else
			echo "ERROR: $CCPROJECTS/$project does not exist ... skipping."
		fi
	done
else
	$CCSTARTSCRIPT $CCARGS > $CCLOGS/stdout.log 2>&1 &
fi

The following simple script can then be used to invoke builds via JMX on the command line. It takes the project name and optionally the build targets as arguments.

invoke-build.sh
#!/bin/sh

JMXURL="http://localhost:8000"

if [ -z "$1" ]; then
        echo "ERROR: You have to pass a project name as argument"
        echo "Usage: $0 <project> [<targets>...]"
        exit 1
else
        project="$1"
        shift
fi

# Checkout projects:
if [ "$1" ]; then
        targets=`echo $@ | sed -e 's/ /+/g'`
        params="operation=buildWithTarget&value0=$targets&type0=java.lang.String"
else
        params="operation=build"
fi

stat=`curl -s "$JMXURL/invoke?objectname=CruiseControl+Project:name=$project&$params&template=identity" | perl -pe 's/>/>\n/g' \
   | grep '<Operation ' | cut -d '"' -f 6`

# above was one line, broken to fit better on the wiki
# if it doesn't work as written, reappend the line starting with a pipe "|" to the one above. -quig

echo "Invokation: $stat"

The /etc/init.d/cruisecontrol script is broken since CruiseControl v2.7.  Reason is that CruiseControlControl.getProjects() is now returning a list of ProjectConfigs (previously a list of Projects) and ProjectConfig.toString() isn't implemented so the curl call just sees a list of:

  <Element element="net.sourceforge.cruisecontrol.ProjectConfig@713fd602" elementclass="net.sourceforge.cruisecontrol.ProjectConfig" index="0"/>

Previously it would return all projects names and statuses.

Anyone have any clues as to how this can be fixed or worked around?  I imagine a patch could add a toString() to ProjectConfig which simply delegates to the Project's toString... ?

I encountered a problem using /etc/init.d/cruisecontrol script above with binary distribution. Although I can specify path to cruisecontrol.log file, cruisecontrol.log is always additionally created in $CC_INSTALL_DIR. So two copies of the log file is created.

This problem is due to log4j.properties supplied with CC also specifies file appender to create cruisecontrol.log in CC_HOME. The init.d script only redirects console output, leaving file appender still creating the log file in CC_HOME.

What I have to do is to supply my own log4j.properties and specify path to log file myself, and let the init.d script redirect only standard output, not the log output.

Mark,

I just committed a change to ProjectConfig to delegate toString() to Project as you suggested. Please holler if that does not fix the issue.

 Dan Rollo

Powered by a free Atlassian Confluence Open Source Project / Non-profit License granted to ThoughtWorks, Inc.. Evaluate Confluence today.
Powered by Atlassian Confluence 2.7.1, the Enterprise Wiki. Bug/feature request - Atlassian news - Contact administrators