May 2008


Here is an init script to control hudson start up at boot time. It is tested on SLES 10 . I am not commenting it in detail here, nevertheless you are welcome to ask and leave comments. It’s rather beta but I hope that it could be useful as a starting point.

#!/bin/bash
# Author: Konstantin.rekk@gbv.de, 2008
# Using ideas from http://developer.novell.com/wiki/index.php/Writing_Init_Scripts
#
# install:
# copy to /etc/init.d/gbv-hudson-integration
# ln -s /etc/init.d/gbv-hudson-integration /sbin/rcgbv-hudson-integration
# insserv /etc/init.d/gbv-hudson-integration
 
 
### BEGIN INIT INFO
# Provides:          gbv-hudson-integration
# Required-Start:    $local_fs $network
# Required-Stop:
# Default-Start:     3 5
# Default-Stop:      0 1 2 6
# Short-Description: Starts the hudson server for CI 
# Description:       Starts Continuous Integration System for VZG SOA
### END INIT INFO
 
# to avoid conflict with functions local $1
ARG=$1
 
APP="hudson"
 
HUDSON_USER=soarun
HUDSON_GROUP=soarun
export HOME=/home/${HUDSON_USER}
export VZGSOA_HOME=${HOME}/soa-workarea
 
# include rc.status functions 
test -s /etc/rc.status && . /etc/rc.status && rc_reset
 
# use test_for_app <appl|file> (x|f)
test_for_app ()
{
    app_found=0
    if [ "f" = "$2" ] && [ -f $1 ]; then
        app_found=1
    elif [ "x" = "$2" ] && [ -x $1 ]; then
        app_found=1
    fi
    if [ 0 = $app_found ]; then
        echo -n "Warning:  Couldn't find $1"
        if [ "$ARG" = "stop" ] ; then
            rc_failed 0
        else
            rc_failed 5
        fi
        rc_status -v
        rc_exit
    fi
}
 
test_for_app $VZGSOA_HOME/vzgsoa.env f
test_for_app $VZGSOA_HOME/integration/integration.env f
. $VZGSOA_HOME/vzgsoa.env
. $VZGSOA_HOME/integration/integration.env
 
HUDSON_CMD="${JAVA} -jar ${HUDSON_WAR} --httpPort=${CI_HTTP_PORT} --argumentsRealm.passwd.hudson=${HUDSON_PW} --argumentsRealm.roles.hudson=admin"
 
HUDSON_PIDFILE=/var/run/hudson.pid
HUDSON_LOG=/var/log/hudson
 
usage ()
{
    echo ""
    echo "Usage: $0 <command> "
    echo ""
    echo "where <command> is one of the following:"
    echo "    start - start $APP if not running"
    echo "    stop - stop $APP if running"
    echo "    status - report whether $APP is running"
    echo "    restart - stop and restart $APP"
    echo "    usage, help - print this message"
}
 
get_pid_for_cmd ()
{
    for pid in `ls /proc`; do
        if [ -d /proc/$pid ] && [ -f /proc/$pid/cmdline ]; then
            if [ "$1" = "$(</proc/$pid/cmdline)" ]; then
		# return with current pid 
                return
            fi
        fi
    done
    pid=0
}
 
# checkport <port>
# returns port_used
check_port()
{
	port=$1
	if netstat -nlept 2>/dev/null | grep --regexp=":$port " &>/dev/null ; then
        	port_used=1
    	else
        	port_used=0
    	fi
}
 
# checks hudson, sets/returns status - 
# 0 if pidfile same as pid, running
# 3 no pidfile, not running (what with running?)
# 2 pidfile, but no process (remove file ...), not running
# 1 pidfile != pid, but running
# 4 no pidfile, but running
# 
# @todo: check port usage
check_hudson() 
{
	get_pid_for_cmd `eval echo ${HUDSON_CMD} | sed -e 's/ //g'`
 
	if [ -f $HUDSON_PIDFILE ]; then
		pidfile_pid=`cat $HUDSON_PIDFILE`
		if [ 0 = $pid ]; then
			status=2
		elif [ "$pid" = "$pidfile_pid" ]; then
			status=0;
		else 
			status=1;
		fi		
	else 
		if [ 0 = $pid ]; then
			status=3;
		else 
			status=4;
		fi
	fi
 
}
 
 
test_for_app ${JAVA} x
test_for_app ${HUDSON_WAR} f
 
case "$1" in
    start)
        check_hudson
        case "$status" in
            0)
                echo "${APP} already running"
		rc_failed 0
		rc_status -v1
           	rc_exit
                ;;
	    1|4)
		echo "${APP} seems running but pidfile is not up to date or doesn't exist, please check!"
		rc_failed
                rc_status -v1
                rc_exit
		;;
            2)
                echo "Found stale pidfile for ${APP} - unclean shutdown?"
                rm ${HUDSON_PIDFILE}
                ;;
            3)
                # not running - ok
        	check_port $CI_HTTP_PORT
		if [ $port_used = 1 ]; then
			echo "Port $CI_HTTP_PORT already in use, pleas check!"
                	rc_failed
                	rc_status -v1
                	rc_exit
		fi 
                ;;
            *)
                echo "Check for ${APP} failed"
                rc_failed
                rc_status -v1
                rc_exit
        esac
 
        echo -n "Starting ${APP}"
        startproc -f -u $HUDSON_USER -g $HUDSON_GROUP -p ${HUDSON_PIDFILE} ${HUDSON_CMD} >> ${HUDSON_LOG} 2>&1
        if ! [ 0 = $? ]; then
            echo -n "(Error - "
            case $? in
                2)
                    echo -n "invalid arguments"
                    ;;
                4)
                    echo -n "insufficient permission"
                    ;;
                5)
                    echo -n "no such program"
                    ;;
                7)
                    echo -n "launch failure"
                    ;;
                *)
                    echo -n "unspecified error"
                    ;;
            esac
            echo -n ")"
            rc_failed
            rc_status -v1
            rc_exit
        fi
	# removing spaces from commandline to be able to compare with /proc/<pid>/cmdline
        get_pid_for_cmd `eval echo ${HUDSON_CMD} | sed -e 's/ //g'`
        if [ 0 = $pid ]; then
            echo "Warning - Couldn't obtain PID for ${APP} "
        else
            echo $pid > ${HUDSON_PIDFILE}
        fi
        rc_status -v
        ;;
    stop)
        if [ $1 = "stop" ]; then
            check_hudson
	    if ! [ $status = 0 ]; then
		echo "Warning - not running!"
	    fi
            killproc -p ${HUDSON_PIDFILE} -t 10 ${JAVA}
            rc_status -v
        fi
        ;;
    status)
        check_hudson
	case "$status" in
        0)
            echo -n "(running)"
            rc_failed 0
            ;;
	1|4)  
	    echo -n "(running)"
	    echo -n  "Warning - PID corrupted"
            rc_failed 0
            ;;
        2)
            echo "(not running)"
            echo -n "Warning - PID file found"
            rc_failed 3
            ;;
        3)
            echo -n "(not running)"
            rc_failed 1
            ;;
        *)
            echo "(unknown)"
            echo "Warning - Couldn't get status"
            rc_failed 1
            rc_status -v1
            rc_exit
    esac
    rc_status -v
        ;;
    restart)
        $0 stop &>/dev/null
        $0 start &>/dev/null
        rc_status -v
        ;;
    usage|help)
        usage
        rc_exit
        ;;
    *)
        usage
        rc_failed 1
        rc_status -v
        rc_exit
esac

Subversion clients store authentication data in ./subversion/auth for each realm.

To remove cached data go to “.subversion/auth/svn.simple” folder and delete the particular file.
There will be key (K)-value (V) pairs. “username” and “svn:realmstring” together can identify the user.
So use for example:

grep servername ./*

to find the right file.

Disable caching by opening “config” file in “.subversion” folder and setting the values of “store-passwords” and “store-auth-creds” to “no” or use –no-auth-cache as command line argument.

ls -d --sort=time */ | head -n 1

Since Version 1.1 subversion can deal with symlinks (see Does Subversion support symlinks?). There are only a few remarks in the manual Versioned Properties – svn:special and ’svn add’ command.

Actually all handling of the symbolic link is up to the client. Cause in creation of symlinks the used paths do matter and subversion stores the link target in simple text file with the appropriate relative or absolute path you should choose the way you create your symlinks with care.

Example – Creating a symlink in your working copy:

$ mkdir A
$ ln -s A link
$ svn add --force .
A A
A link
$ svn commit -m "link there"

the contents of the link file in svn:
link A

Example – change symlink target
$ svn del --force link
$ svn commit -m "no link"
$ mkdir B
$ ln -s B link
$ svn add --force .
$ svn commit -m "link changed to B"

the contents of the link file in svn:
link B

To exclude certain files and directories from subversion’s version control you can set the ’svn:ignore’ property as described in Ignoring Unversioned Items.
That works fine but nevertheless you might run into problems if you are using
svn add *
or similiar on linux systems. This is due to the shell expansion of wildcards. The above command is expanded to explicit files names svn add filename and seems to have the same effect as svn add --no-ignore filename.
Tip: Use svn add --force . instead!