init.d Scripts

The init.d scripts are very useful when it's necessary to run some application once the system is up and running. There are many init.d scripts in almost any GNU/Linux distribution, and they mostly satisfy the needs of an average user. But sometimes it's hard to find either a good or a working init.d script for a less used task.

Additionally, different GNU/Linux distributions very often use different formats for init.d scripts. As an example, an init.d script working under Debian will not work under Gentoo, and vice-versa. When I have time, I'll be adding init.d scripts for all the distributions I'm using.

This book is dedicated to describing various init.d script I've created during my years of work with GNU/Linux. In addition, the book also contains the copies of init.d scripts I'm using on production machines under my control. Practically all the scripts presented in this book require usage of bash, which makes them somewhat less portable, but still very usable nevertheless.

I encourage you to inform me of any mistakes I made while writing those scripts, as well as suggestions as to how I could improve them or add new features.

Running irssi on Boot

When it comes down to IRC clients, there's not many that can be compared to flexibility and extendibility provided by irssi (http://irssi.org/), an excellent terminal-based client, which combined with the GNU Screen (http://www.gnu.org/software/screen/) can provide constant presence on IRC channels of any network (provided that you have a constantly working server/desktop connected to the Internet).

Many users will run their irssi application the moment the login into machine. Although quite normal, many users will want to automate the process. One possibility is to use the following snippet of code added to your ~/.bashrc file:

# Start an irssi under screen if it wasn't started before
if ! pidof irssi > /dev/null; then
    screen -d -m -S irssi irssi
fi

This is a very good solution when you know you're going to login straight away onto machine once it boots-up, and you know it won't get rebooted because of power failure or human intervention. It's also a good solution when you do not have access to system administrator account.

But if you do have access to the administrator account (the omnipotent root), you could have irssi started-up for a number of users using an init.d script.

Under Debian

In addition to having the irssi package installed, don't forget to install screen:

$ apt-get install screen

Paste the following contents into file located at /etc/init.d/irssid:

#!/bin/bash

### BEGIN INIT INFO
# Provides:          irssid
# Required-Start:    $network
# Required-Stop:     $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start irssi daemon within screen session at boot time
# Description:       This init script will start an irssi session under screen using the settings provided in /etc/irssid.conf
### END INIT INFO

# Include the LSB library functions
. /lib/lsb/init-functions

# Setup static variables
configFile='/etc/irssid.conf'
daemonExec='/usr/bin/screen'
daemonArgs='-D -m'
daemonName="$(basename "$daemonExec")"
pidFile='/var/run/irssid.pid'

#
# Checks if the environment is capable of running the script (such as
# availability of programs etc).
#
# Return: 0 if the environmnt is properly setup for execution of init script, 1
#         if not all conditions have been met.
#
function checkEnvironment() {
    # Verify that the necessary binaries are available for execution.
    local binaries=(irssi screen)

    for bin in "${binaries[@]}"; do
        if ! which "$bin" > /dev/null; then
            log_failure_msg "Binary '$bin' is not available. Please install \
package containing it."

            exit 5
        fi
    done
}

#
# Checks if the configuration files are available and properly setup.
#
# Return: 0 if irssid if properly configured, 1 otherwise.
#
function checkConfig() {
    # Make sure the configuration file has been created
    if ! [[ -f $configFile ]]; then
        log_failure_msg "Please populate the configuration file '$configFile' \
before running."

        exit 6
    fi

    # Make sure the required options have been set
    local reqOptions=(user group session)
    for option in "${reqOptions[@]}"; do
        if ! grep -q -e "^[[:blank:]]*$option=" "$configFile"; then
            log_failure_msg "Mandatory option '$option' was not specified in \
'$configFile'"

            exit 6
        fi
    done
}

#
# Loads the configuration file and performs any additional configuration steps.
#
function configure() {
    . "$configFile"
    daemonArgs="$daemonArgs -S $session irssi"
    [[ -n $args ]] && daemonArgs="$daemonArgs $args"
    daemonCommand="$daemonExec $daemonArgs"
}

#
# Starts the daemon.
#
# Return: LSB-compliant code.
#
function start() {
    start-stop-daemon --start --quiet --oknodo --pidfile "$pidFile" \
        --make-pidfile --chuid "$user:$group" --background \
        --exec "$daemonExec" -- $daemonArgs
}

#
# Stops the daemon.
#
# Return: LSB-compliant code.
#
function stop() {
    start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile "$pidFile" \
        --chuid "$user:$group" --exec "$daemonExec" -- $daemonArgs
}

checkEnvironment
checkConfig
configure

case "$1" in
    start)
        log_daemon_msg "Starting daemon" "irssid"
        start && log_end_msg 0 || log_end_msg $?
        ;;
    stop)
        log_daemon_msg "Stopping daemon" "irssid"
        stop && log_end_msg 0 || log_end_msg $?
        ;;
    restart)
        log_daemon_msg "Restarting daemon" "irssid"
        stop
        start && log_end_msg 0 || log_end_msg $?
        ;;
    force-reload)
        log_daemon_msg "Restarting daemon" "irssid"
        stop
        start && log_end_msg 0 || log_end_msg $?
        ;;
    status)
        status_of_proc -p "$pidFile" "$daemonExec" screen && exit 0 || exit $?
        ;;
    *)
        echo "irssid (start|stop|restart|force-reload|status|help)"
        ;;
esac

Configuration file where you can specify the user, group, and pass additional options for irssi should be placed withing /etc/irssid.conf. Here's an example file with comments:

#
# Configuration file for irssid init script
#
# Mandatory options:
#
#    user    - Specify user for running irssi.
#    group   - Specify group for running irssi.
#    session - Specify screen session name to be used for irssi.
#
# Non-mandatory options:
#
#    args    - Pass additional arguments to irssi.
#

# Example configuration:
#user='john'
#group='users'
#session='irssi'
#args='--config /home/john/.irssi/config_alternative'

Now you can start, stop, or check status of your irssi screen session using the following commands:

$ /etc/init.d/irssid start
$ /etc/init.d/irssid stop
$ /etc/init.d/irssid status

Finally, when you're satisfied with the options you made, you can add the irssid to appropriate runlevels with:

$ update-rc.d irssid defaults

Under Gentoo

In addition to having irssi installed, make sure you install the screen package:

$ emerge screen

Paste the following contents into file located at /etc/init.d/irssid:

#!/sbin/runscript

# Setup static variables
configFile='/etc/conf.d/irssid'
daemonExec='/usr/bin/screen'
daemonArgs='-D -m'
daemonName="$(basename "$daemonExec")"
pidFile='/var/run/irssid.pid'

#
# Checks if the environment is capable of running the script (such as
# availability of programs etc).
#
# Return: 0 if the environmnt is properly setup for execution of init script, 1
#         if not all conditions have been met.
#
function checkEnvironment() {
    # Verify that the necessary binaries are available for execution.
    local binaries=(irssi screen)

    for bin in "${binaries[@]}"; do
        if ! which "$bin" > /dev/null; then
            eerror "Binary '$bin' is not available. Please install \
package containing it."

            exit 5
        fi
    done
}

#
# Checks if the configuration files are available and properly setup.
#
# Return: 0 if irssid if properly configured, 1 otherwise.
#
function checkConfig() {
    # Make sure the configuration file has been created
    if ! [[ -f $configFile ]]; then
        eerror "Please populate the configuration file '$configFile' \
before running."

        exit 6
    fi

    # Make sure the required options have been set
    local reqOptions=(user group session)
    for option in "${reqOptions[@]}"; do
        if ! grep -q -e "^[[:blank:]]*$option=" "$configFile"; then
            eerror "Mandatory option '$option' was not specified in \
'$configFile'"

            exit 6
        fi
    done
}

#
# Loads the configuration file and performs any additional configuration steps.
#
function configure() {
    daemonArgs="$daemonArgs -S $session irssi"
    [[ -n $args ]] && daemonArgs="$daemonArgs $args"
    daemonCommand="$daemonExec $daemonArgs"
}

checkEnvironment
checkConfig
configure

#############################
# Gentoo-specific functions #
#############################

depend() {
    need net localmount
    after bootmisc
}

start () {
    ebegin "Starting irssid"
    start-stop-daemon --start --quiet --oknodo --pidfile "$pidFile" \
        --make-pidfile --chuid "$user:$group" --background \
        --exec "$daemonExec" -- $daemonArgs
    eend $?
}

stop () {
    ebegin "Stopping irssid"
    start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile "$pidFile" \
        --chuid "$user:$group" --exec "$daemonExec" -- $daemonArgs
    eend $?
}

Configuration file where you can specify the user, group, and pass additional options for irssi should be placed withing /etc/conf.d/irssi. Configuration file syntax is the same as for Debian script.

Now you can start, stop, or check status of your irssi screen session using the following commands:

$ /etc/init.d/irssid start
$ /etc/init.d/irssid stop
$ /etc/init.d/irssid status

Finally, when you're satisfied with the options you made, you can add the irssid to any runlevel you prefer (let's say the default one):

$ update-rc add irssid default