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:# 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:# default CC_WEBPORT=8080
CC_WEBPORT=8080
# JMX port for webapp and Java Management eXtensions (JMX). You can access it by going to http:# 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.
#!/bin/sh
# chkconfig: 2345 95 05
# description: CruiseControl build loop
#
# based on http:# 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:
# 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
#!/bin/sh
# run cruisecontrol for the various projects
# started by /etc/init.d/cruisecontrol which sets up the environment
# Originally taken from http:
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.
#!/bin/sh
JMXURL="http:
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