placing shell script under systemd control

Assuming I have a shell script like this:-

#!/bin/sh
# cherrypy_server.sh

PROCESSES=10
THREADS=1 # threads per process
BASE_PORT=3035 # the first port used
# you need to make the PIDFILE dir and insure it has the right permissions
PIDFILE="/var/run/cherrypy/myproject.pid"
WORKDIR=`dirname "$0"`
cd "$WORKDIR"

cp_start_proc()
{
 N=$1
 P=$(( $BASE_PORT + $N - 1 ))
 ./manage.py runcpserver daemonize=1 port=$P pidfile="$PIDFILE-$N" threads=$THREADS request_queue_size=0 verbose=0
}

cp_start()
{
 for N in `seq 1 $PROCESSES`; do
  cp_start_proc $N
 done
}

cp_stop_proc()
{
 N=$1
 #[ -f "$PIDFILE-$N" ] && kill `cat "$PIDFILE-$N"`
 [ -f "$PIDFILE-$N" ] && ./manage.py runcpserver pidfile="$PIDFILE-$N" stop
 rm -f "$PIDFILE-$N"
}

cp_stop()
{
 for N in `seq 1 $PROCESSES`; do
  cp_stop_proc $N
 done
}

cp_restart_proc()
{
 N=$1
 cp_stop_proc $N
 #sleep 1
 cp_start_proc $N
}

cp_restart()
{
 for N in `seq 1 $PROCESSES`; do
  cp_restart_proc $N
 done
}

case "$1" in
 "start")
  cp_start
 ;;
 "stop")
  cp_stop
 ;;
 "restart")
  cp_restart
 ;;
 *)
  "$@"
 ;;
esac

From the bash script, we can essentially do 3 things:

  1. start the cherrypy server by calling ./cherrypy_server.sh start
  2. stop the cherrypy server by calling ./cherrypy_server.sh stop
  3. restart the cherrypy server by calling ./cherrypy_server.sh restart

How would I place this shell script under systemd's control as a cherrypy.service file (with the obvious goal of having systemd start up the cherrypy server when a machine has been rebooted)?

Reference systemd service file example here - https://wiki.archlinux.org/index.php/Systemd#Using_service_file


I use those for Sick Beard and SabNZBd, two python/cherrypy apps. The difference is knowing when to use 'forking'. That basically tells systemd that the main binary will fork stuff so it has to guess the PID from a file. WantedBy is just to define the target that will require this to start, think it as runlevel. You will notice also that the second definition uses a directory to keep run information, that's because it creates a $process-$port for each started daemon (you may have many daemons spawned by the main one on different ports).

IMO you can add the script on ExecStart and make sure that it is forking and add a way for it to find the main PIDfile, or at least a PIDfile that means 'if this is dead, restart the service'.

Maybe the ideal is to create 1 service file with 'simple' for each daemon?

[Unit]
Description=Internet PVR for your TV Shows
After=cryptsetup.target

[Service]
ExecStart=/usr/bin/python2 /path/to/Sick-Beard/SickBeard.py
Type=simple
User=<user under which to run>
Group=<group of said user>

[Install]
WantedBy=multi-user.target

And this one is the forking one

[Unit]
Description=Binary Newsreader
After=cryptsetup.target

[Service]
ExecStart=/usr/bin/python2 /path/to/sabnzbd/SABnzbd.py -d -f /path/to/inifile --pid /run/sabnzbd
Type=forking
PIDFile=/run/sabnzbd/sabnzbd-8080.pid
User=<user to run the process>
Group=<group of said user>

[Install]
WantedBy=multi-user.target