#!/bin/bash # rc.d script that launch service defined in systemd service unit # Symlink this to same name as systemd unit has(without .service extension) # and run as usual # (Example: ln -s systemd-unit NetworkManager) # Version 0.1 # TODO: ExecStartPre, ExecStartPost (AFAIK not used by any actual service in Arch) . /etc/rc.conf . /etc/rc.d/functions function read_ini { # filename, key, default value x=$(cat $1 | egrep "^[ ]*""$2""[ ]*"= | cut -d = -f 2-) [ x"$x" == x ] && x="$3" echo "$x" } function smallest_pidof { # program # Gets smallest PID of specified program. Parameters are ignored pidof -x $1 | tr " " "\n" | sort | head -1 } function nice_kill { # PID # Sends SIGTERM, waits 5 secs (if necessary) and then kills kill $PID sleep 0.1 kill -0 $PID 2>/dev/null || return 0 for i in 1 2 3 4 5 ; do sleep 1 kill -0 $PID 2>/dev/null || return 0 done kill -9 $PID echo "Killed." >/dev/stderr } # Detect service name and systemd unit file SERVICE=$(basename $0) FILE=/usr/lib/systemd/system/$SERVICE.service # Read configuration DESC=$(read_ini $FILE Description $SERVICE) ENVIRON=$(read_ini $FILE EnvironmentFile) ENVIRON=${ENVIRON#"-"} TYPE=$(read_ini $FILE Type simple) [ x"$ENVIRON" != x ] && [ -e "$ENVIRON" ] && source "$ENVIRON" case "$1" in start) EXEC=$(read_ini $FILE ExecStart /bin/false) EXEC=$(eval echo $EXEC) if [ x"$TYPE" == xforking ] ; then # Forking service stat_busy "Starting $DESC" if $EXEC ; then add_daemon $SERVICE stat_done else stat_fail exit 1 fi elif [ x"$TYPE" == xoneshot ] ; then # Oneshot stat_busy "Executing $DESC" if $EXEC ; then stat_done else stat_fail exit 1 fi else # Everything else (dbus, notify, idle, simple) stat_busy "Starting $DESC" if [[ "$EXEC" == -* ]] ; then # There is no need to check if daemon is really running EXEC=${EXEC#"-"} $EXEC &>/dev/null & stat_done else # Daemon is launched on background and it's excepted to stay alive $EXEC &>/dev/null & sleep 0.1 if [ x$(smallest_pidof $EXEC) != x ] ; then stat_done else stat_fail exit 1 fi fi fi ;; stop) if [ x"$TYPE" == xoneshot ] ; then # stop command is not available for oneshots; displays help message $0 exit 1 fi PIDFILE=$(read_ini $FILE PIDFile) EXEC=$(read_ini $FILE ExecStop) PID="" stat_busy "Stopping $DESC" if [ x"$PIDFILE" != x ] ; then # Read PID from defined PID file PID=$(cat $PIDFILE 2>/dev/null) if [ x"$PID" == x ] ; then echo "Failed to read PID file $PIDFILE" >/dev/stderr stat_fail exit 1 fi fi if [ x"$EXEC" != x ] ; then # Stop using defined command MAINPID=$PID EXEC=$(eval echo $EXEC) if [[ "$EXEC" == -* ]] ; then # There is no need to check if command was sucessfull EXEC=${EXEC#"-"} $EXEC stat_done else if $EXEC ; then stat_done else stat_fail exit 1 fi fi elif [ x"$PID" != x ] ; then # Stop using PID from PID file nice_kill $PID rm_daemon $SERVICE stat_done else # Stop using PID of program defined in ExecStart EXEC=$(read_ini $FILE ExecStart /bin/false) PID=$(smallest_pidof $EXEC) if [ x"$PID" == x ] ; then echo "Service is already stopped" >/dev/stderr stat_fail exit 1 fi nice_kill $PID rm_daemon $SERVICE stat_done fi ;; restart) if [ x"$TYPE" == xoneshot ] ; then # Oneshot cannot be restarted. Display help $0 exit 1 else RESTARTSEC=$(read_ini $FILE RestartSec 0.1) $0 stop sleep $RESTARTSEC $0 start fi ;; reload) EXEC=$(read_ini $FILE ExecReload) if [ x"$EXEC" != x -a x"$TYPE" != xoneshot ] ; then stat_busy "Reloading $DESC" PIDFILE=$(read_ini $FILE PIDFile /dev/null) MAINPID=$(cat $PIDFILE 2>/dev/null) [ x"$MAINPID" == x ] && MAINPID=$(smallest_pidof $(read_ini $FILE ExecStart /bin/false) ) EXEC=$(eval echo $EXEC) if $EXEC ; then stat_done exit 0 else stat_fail exit 1 fi else $0 # reload command is not available; displays help message exit 1 fi ;; *) RELOADEXEC=$(read_ini $FILE ExecReload) USAGE="start" [ x"$TYPE" != xoneshot ] && USAGE="$USAGE|stop|restart" [ x"$RELOADEXEC" != x ] && USAGE="$USAGE|reload" echo "usage: $0 {$USAGE}" >&2 exit 1 ;; esac