# Converting a Linux java init.d to rc.d



## Beeblebrox (Mar 8, 2013)

I'm trying to get Jenkins to start as a daemon from /etc/rc.conf. The folks at Jenkins advised that the best way to do this would be to use an "init script" passing this bit of code:

```
java -jar slave.jar -jnlpUrl http://master-IP:8180/jenkins/computer/nodename/slave-agent.jnlp
```
I found this ready piece of init written for this purpose and set about modifying it for FreeBSD. As the script should be placed in /usr/local/etc/rc.d and since that location does not have a defaults folder, I decided to merge the default settings directly into the script.  I made some headway, but in the end, java does not like the command being passed and gives two pages of advice on what arguments it will accept. Obviously I have overlooked something.

For those who are unaware, Jenkins can be used for "distributed compile" (for package building for example) together with poudriere. The old method of using distcc for the task does not work on 10-Current, mainly because distcc does not work yet with clang! 

Anyway, the problem part of the script is in "do_start()" and I also don't understand why the script decides to call "su"?

```
$SU -l ${JENKINS_USER} --shell=/bin/sh -c "${DAEMON} ${DAEMON_ARGS} -- ${JAVA} ${JAVA_ARGS} -jar ${JENKINS_WAR} ${JENKINS_ARGS}" || return 2
```
The whole script:

```
#!/bin/sh
#
# PROVIDE: jenkinsjslave
# REQUIRE: $remote_fs $syslog $network
# BEFORE: LOGIN
# KEYWORD: shutdown
#
# Short-Description: Start jenkins at boot time
# Description: Controls the jenkins continuous integration engine.
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service: jenkinsjslave_enable (bool)
# Set to NO by default, set it to YES to enable.

. /etc/rc.subr

NAME=jenkinsjslave
rcvar=${NAME}_enable
jenkinsjslave_enable=${jenkinsjslave_enable-"NO"}
SCRIPTNAME=/usr/local/etc/rc.d/${NAME}

#DEFAULTS - [ -r /etc/defaults/$NAME ] && . /etc/defaults/$NAME
JENKINS_HOME=/usr/local/jenkins/war/WEB-INF
JENKINS_WAR=${JENKINS_HOME}/slave.jar
# location of java  JAVA=/usr/local/openjdk7/bin/java
JAVA_VERSION=1.7 /usr/local/bin/java
# make jenkins listen on IPv4 address
JAVA_ARGS="-Djava.net.preferIPv4Stack=true"
PIDFILE=/var/run/jenkins/jenkinsjslave.pid
JENKINS_USER=jenkins-builder
RUN_STANDALONE=true
MAXOPENFILES=8192
HTTP_PORT=8180
AJP_PORT=-1
NODE=uname -n
JENKINS_LOG=/usr/obj/jenkins/logs/${NODE}.log
JENKINS_ARGS="-jnlpUrl http://192.168.2.1:8180/jenkins/computer/"${NODE}"/slave-agent.jnlp"

#DAEMON=$JENKINS_SH
DAEMON=/usr/sbin/daemon
daemon_args="--name=${NAME} --inherit --env=JENKINS_HOME=${JENKINS_HOME} --output=${JENKINS_LOG} --pidfile=${PIDFILE}"

SU=/usr/bin/su

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Exit if not supposed to run standalone
[ "$RUN_STANDALONE" = "false" ] && exit 0

# load environments
if [ -r /etc/defaults/locale ]; then
. /etc/defaults/locale
export LANG LANGUAGE
elif [ -r /etc/environment ]; then
. /etc/environment
export LANG LANGUAGE
fi

# Load the VERBOSE setting and other rcS variables
#. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
#. /lib/lsb/init-functions

# Make sure we run as root, since setting the max open files through
# ulimit requires root access
#if [ `id -u` -ne 0 ]; then
#echo "The $NAME service can only be started as root"
#exit 1
#fi

check_tcp_port() {
local service=$1
local assigned=$2
local default=$3

if [ -n "$assigned" ]; then
port=$assigned
else
port=$default
fi
count=`netstat --listen --numeric-ports | grep \:$port[[:space:]] | grep -c . `
if [ $count -ne 0 ]; then
echo "The selected $service port ($port) seems to be in use by another program "
echo "Please select another port to use for $NAME"
return 1
fi
}

#
# Function that starts the daemon/service
#
do_start()
{
# the default location is /var/run/jenkins/jenkins.pid but the parent directory needs to be created
mkdir `dirname ${PIDFILE}` > /dev/null 2>&1 || true
chown ${JENKINS_USER} `dirname ${PIDFILE}`
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
${DAEMON} ${DAEMON_ARGS} --running && return 1

# If the var MAXOPENFILES is enabled in /etc/default/jenkins then set the max open files to the
# proper value
if [ -n "$MAXOPENFILES" ]; then
[ "$VERBOSE" != no ] && echo Setting up max open files limit to $MAXOPENFILES
ulimit -n ${MAXOPENFILES}
fi
# --user in daemon doesn't prepare environment variables like HOME, USER, LOGNAME or USERNAME,
# so we let su do so for us now
#$SU -l ${JENKINS_USER} --shell=/bin/sh -c "${DAEMON} ${DAEMON_ARGS} -- ${JAVA} ${JAVA_ARGS} -jar ${JENKINS_WAR} ${JENKINS_ARGS}" || return 2

# Disabled the JAVA_ARGS bit to see if it would work, but no...
${JAVA} -jar ${JENKINS_WAR} ${JENKINS_ARGS}
}

#
# Verify that all jenkins processes have been shutdown
# and if not, then do killall for them
#
get_running()
{
return `ps -U ${JENKINS_USER} --no-headers -f | egrep -e '(java|daemon)' | grep -c . `
}

force_stop()
{
get_running
if [ $? -ne 0 ]; then
killall -u ${JENKINS_USER} java daemon || return 3
fi
}
```
The code goes on for a little more (you can see the original from the link) but my current problem is about getting the thing sastrted in the first place. As you can also see, I disabled some of the non-critical code because I have yet to find the FreeBSD equivalent parts for it.
If I start the command by typing it in the node, java starts without complaints.


----------



## redw0lfx (Mar 8, 2013)

Not sure if you noticed, but your JENKINGS_ARGS has a typo, its missing a '-' for jnlpUrl.


```
JENKINS_ARGS="-jnlpUrl http://192.168.2.1:8180/jenkins/computer/"${NODE}"/slave-agent.jnlp"
```


----------



## redw0lfx (Mar 8, 2013)

Discard the above statement, it is correct.  I was able to convert the provided /usr/local/etc/rc.d/jenkins script to jenkinsslave and just changed all variables from jenkins to jenkinsslave.

And set the following variable as follows:

```
: ${jenkinsslave_args="-jnlpUrl http://127.0.0.1:8180/jenkins/computer/firefly/slave-agent.jnlp -secret xxxxxxxxxxxxxxxxxxxx"}
```

I left everything else the same (in reality, a lot of the extra variables can be cleaned up).

If you get an error, check towards the top of the error, it should list which parameter it didn't like.


----------



## Beeblebrox (Mar 9, 2013)

> I was able to convert the provided /usr/local/etc/rc.d/jenkins script to jenkinsslave


That's a good idea - looking through jenkins. There's a problem with your jenkinsjslave_arg however, the IP needs to be that of the master node, not the slave's lo. Anyway, I modified the jenkins file but now I have run into some different problems. I started new threads for those.

Thanks again for the input.


----------

