Creating a Java Daemon (System Service) for Debian using Apache Commons Jsvc

daemon is a computer program that runs as a background process, executing tasks on a predefined schedule or in response to particular events, or in response to requests for information or services from other programs.

To start up a Java program as a daemon using Jsvc, we’ll need to do a few things:

a) Implement the Apache Commons Daemon interface.

b) Install Jsvc by downloading and compiling the source (C) or via the command line with the sudo apt-get install jsvc command.

c) Create a bash shell script to launch the daemon and manage the basic set of daemon controls, namely: startstop restart. Others include reload status.

Implementing the Java Daemon Interface

Implementing the Daemon interface is a fairly simple undertaking. Once you have downloaded the library from the Apache Commons project site and referenced it in your Java project, you can go about creating your implementation as follows:


import org.apache.commons.daemon.Daemon;
import org.apache.commons.daemon.DaemonContext;
import org.apache.commons.daemon.DaemonInitException;

public class MyDaemon implements Daemon {

private Thread myThread;
private boolean stopped = false;
private boolean lastOneWasATick = false;

public void init(DaemonContext daemonContext) throws DaemonInitException, Exception {
* Construct objects and initialize variables here.
* You can access the command line arguments that would normally be passed to your main()
* method as follows:

String[] args = daemonContext.getArguments();

myThread = new Thread(){
private long lastTick = 0;

public synchronized void start() {
MyDaemon.this.stopped = false;

public void run() {
long now = System.currentTimeMillis();
if(now - lastTick >= 1000){
System.out.println(!lastOneWasATick ? "tick" : "tock");
lastOneWasATick = !lastOneWasATick;
lastTick = now;

public void start() throws Exception {

public void stop() throws Exception {
stopped = true;
}catch(InterruptedException e){
throw e;

public void destroy() {
myThread = null;

Jsvc seems to require that our program is exported to a jar, which in this instance I have stored at /usr/local/mydaemon/MyDaemon.jar and the Apache Commons Daemon library has been stored at /usr/local/mydaemon/lib/commons-daemon-1.0.15.jar.

Creating a bash shell script to launch the daemon and manage the basic set of daemon controls

Debian daemon init scripts are stored in /etc/init.d/. A skeleton init script, (/etc/init.d/skeleton) is available to copy and modify according to your needs and generally would provide a good starting point for your services’ init script, however, writing an init script for Jsvc is a little different.

So assuming that that your Daemon implementation’s jar file and the Apache Commons Daemon library are stored at the above locations A basic example of a bash init script for our MyDaemon service could look like this:

#! /bin/sh
# /etc/init.d/mydaemon

# Provides: mydaemon
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Short-Description: Starts the MyDaemon service
# Description: This file is used to start the daemon
# and should be placed in /etc/init.d

# Author: Sheldon Neilson <sheldon[AT]>
# Url:
# Date: 25/04/2013

DESC="MyDaemon service"

# The path to Jsvc

# The path to the folder containing MyDaemon.jar

# The path to the folder containing the java runtime

# Our classpath including our jar file and the Apache Commons Daemon library

# The fully qualified name of the class to execute

# Any command line arguments to be passed to the our Java Daemon implementations init() method
ARGS="myArg1 myArg2 myArg3"

#The user to run the daemon as

# The file that will contain our process identification number (pid) for other scripts/programs that need to access it.

# System.out writes to this file...

# System.err writes to this file...

$EXEC -home $JAVA_HOME -cp $CLASS_PATH -user $USER -outfile $LOG_OUT -errfile $LOG_ERR -pidfile $PID $1 $CLASS $ARGS

case "$1" in
echo "Starting the $DESC..."

# Start the service

echo "The $DESC has started."
echo "Stopping the $DESC..."

# Stop the service
jsvc_exec "-stop"

echo "The $DESC has stopped."
if [ -f "$PID" ]; then

echo "Restarting the $DESC..."

# Stop the service
jsvc_exec "-stop"

# Start the service

echo "The $DESC has restarted."
echo "Daemon not running, no action taken"
exit 1
echo "Usage: /etc/init.d/$NAME {start|stop|restart}" >&2
exit 3

The init script above should be stored in /etc/init.d/ along with the system’s other start-up scripts.

Automatically Starting the Daemon at System Boot

With our init script done, we need to change it’s permissions to make it executable using chmod. chmod 755 /etc/init.d/mydaemon. And register it for execution as the system’s run level changes.

“Debian uses a Sys-V like system for executing commands when the system runlevel changes, for example at boot and shutdown time.” – Source: Making scripts run at boot time with Debian

As the system’s runlevel changes, any scripts within corresponding /etc/rc*.d/ directory will be executed, where * is the number of the runlevel.

The easiest way to have our script executed appropriately is to use the Debian command update-rc.d to add the appropriate symlinks for us.

To enable our daemon at boot use update-rc.d mydaemon defaults:

root@sheldon-pc:/etc/init.d# update-rc.d mydaemon defaults
 Adding system startup for /etc/init.d/mydaemon...
   /etc/rc0.d/K20mydaemon -> ../init.d/mydaemon
   /etc/rc1.d/K20mydaemon -> ../init.d/mydaemon
   /etc/rc6.d/K20mydaemon -> ../init.d/mydaemon
   /etc/rc2.d/S20mydaemon -> ../init.d/mydaemon
   /etc/rc3.d/S20mydaemon-> ../init.d/mydaemon
   /etc/rc4.d/S20mydaemon -> ../init.d/mydaemon
   /etc/rc5.d/S20mydaemon-> ../init.d/mydaemon

If you should ever wish to disable it, run update-rc.d -f mydaemon remove:

root@sheldon-pc:/etc/init.d# update-rc.d -f mydaemon remove
update-rc.d: /etc/init.d/mydaemon exists during rc.d purge (continuing)
 Removing any system startup links for /etc/init.d/blah ...

Our daemon should now start when the system boots. To view it’s output, first we should stop it to prevent any concurrent access issues when we open the log file: /etc/init.d/mydaemon stop.

As we know that our log file is being created at /usr/local/mydaemon/log/mydaemon.out, we can view it using the command vi /usr/local/mydaemon/log/mydaemon.out

root@sheldon-pc:/etc/init.d# vi /usr/local/mydaemon/log/mydaemon.out