Welcome to bytebang » The blog about all and nothing » Autostart a program on the Raspberry Pi

Autostart a program on the Raspberry Pi

Jun 23 2015

The Problem

When you run a server then the server process has to be started. If you are installing a webserver like apache2 or lighttpd via the package manager then an autostart script will be installed as well. This is not the case if you want to run your self-compiled server like the dump1090 ADS-B receiver. In this case you have to provide the start (and also probably a stop-) script by yourself.

The Solution

The solution is simple. In the first step you have to provide a small script which starts and stops your server. In the second step you have to register it against the operating system. The exact procedure is described below.

A little theory: Linux Runlevels

A runlevel defines the state of the machine after boot. Different runlevels are typically assigned (not necessarily in any particular order) to the single-user mode, multiuser mode without network services started, multiuser mode with network services started, system shutdown, and system reboot system states. The exact setup of these configurations varies between operating systems and Linux distributions. For example, runlevel 4 might be a multi-user GUI no-server configuration on one distribution, and nothing on another. Runlevels commonly follow the general patterns described in this article; however, some distributions employ certain specific configurations.

Raspiban (the standard operating system of a RPi) is related to debian, and in debian runlevels are working as follows:

Where Does a Run Level Live?

Like everything else in a Linux system, run levels are defined by files in the filesystem. All the run level files are found in the directory according to the following table:

/etc/rc0.dRun level 0  Shutdown of the system
/etc/rc1.dRun level 1Singleuser mode at start
/etc/rc2.dRun level 2Multiuser mode
/etc/rc3.dRun level 3-- " --
/etc/rc4.d Run level 4-- " --
/etc/rc5.dRun level 5-- " --
/etc/rc6.dRun level 6Reboot

Notice a pattern? Each defined runlevel should have an rcX.d directory where X is the run level number. The contents of the rcX.d directory determines what happens at that run level.

(S)tart files, (K)ill files

Let's look at run level 2 since this is where we'll spend most of our time. Here are the contents of a generic rc2.d directory:

$ ls -l /etc/rc2.d/
total 4
-rw-r--r-- 1 root root 677 Mär 13 20:49 README
lrwxrwxrwx 1 root root  17 Mär 16  2014 S16openvpn -> ../init.d/openvpn
lrwxrwxrwx 1 root root  15 Nov 25  2014 S20aprsc -> ../init.d/aprsc
lrwxrwxrwx 1 root root  20 Mär  8  2014 S20kerneloops -> ../init.d/kerneloops
lrwxrwxrwx 1 root root  15 Mär  9  2014 S20pcscd -> ../init.d/pcscd
lrwxrwxrwx 1 root root  15 Mär  8  2014 S20rsync -> ../init.d/rsync
lrwxrwxrwx 1 root root  24 Jän 23 13:42 S20screen-cleanup -> ../init.d/screen-cleanup
lrwxrwxrwx 1 root root  23 Mär 30  2014 S20smartmontools -> ../init.d/smartmontools
lrwxrwxrwx 1 root root  27 Mär  8  2014 S20speech-dispatcher -> ../init.d/speech-dispatcher
lrwxrwxrwx 1 root root  13 Mär 12  2014 S20tor -> ../init.d/tor
lrwxrwxrwx 1 root root  14 Mär 16  2014 S20wicd -> ../init.d/wicd
lrwxrwxrwx 1 root root  15 Mär  8  2014 S50saned -> ../init.d/saned
lrwxrwxrwx 1 root root  19 Mär  8  2014 S70dns-clean -> ../init.d/dns-clean
lrwxrwxrwx 1 root root  18 Mär  8  2014 S70pppd-dns -> ../init.d/pppd-dns
lrwxrwxrwx 1 root root  13 Mär 30  2014 S98tlp -> ../init.d/tlp
lrwxrwxrwx 1 root root  21 Mär  8  2014 S99grub-common -> ../init.d/grub-common
lrwxrwxrwx 1 root root  18 Mär  8  2014 S99ondemand -> ../init.d/ondemand
lrwxrwxrwx 1 root root  18 Mär  8  2014 S99rc.local -> ../init.d/rc.local

At first glance the files in this directory look kind of intimidating. They should be. The files in the rcX.d directories are formatted for the computer to read, not the user. Each file is a symbolic link to a script residing in the /etc/init.d directory and controls the starting, or stopping of a program, or daemon (service).

This is important enough to say again, each file is a symbolic link to a script and controls the starting, or stopping of a program, or daemon.

Working backwards, here is how the name parses out. The [string] is a human readable mnemonic for the executable file that is actually symbolically linked to. The 'nn' is a two digit number from 01-99; lower number programs are executed first. By this method, services that have a dependancy can be certain their precursor has ran. The K and S signify simply Kill, or Start.

When a system moves into a new runlevel, all the files that begin with S will be executed. When a system moves into a new runlevel all the files that begin with K will be executed. Yes, all the files will execute, but with one distinct difference: 'S' files invoke their program with the 'start' parameter, the 'K' files invoke their program with the 'stop' parameter. The UserLinux (Debian) system optimizes the runlevel change by not starting a daemon that is already running.

The simple elegance of this system is made possible by the alphabet. All the scripts will execute in alphabetical order. 'K' comes before 'S', so programs are stopped before they are started. Forgetting this fact can lead to a lot of chin scratching while manipulating your rcX.d files.

After the first letter comes the integer, again determining execution order. Finally, the mnemonic portion is followed alphabetically to determine execution order. All of these files have the same precedence as far as the system is concerned. They will be executed in the order listed, i.e. alphabetically. All of the scripts that run during system start-up actually reside in the /etc/init.d/ directory, as suggested by the listing. The reasons for this are many, but basically boil down to common sense issues like: saving space, single point for editing, and everyone knowing where to find things.

The final solution

Finally here is a sample how the content of such start / killscript (in my case the /etc/init.d/dump1090 looks like:

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

# Provides:          dump1090
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Simple script to start the dump1090 receiver.
# Description:       Starts and Stops dump1090 (ADSB)

# If you want a command to always run, put it here

# Carry out specific functions when asked to by the system
case "$1" in
    echo "Starting dump1090"
    # run application you want to start
    start-stop-daemon --start --background --chdir /home/pi/dump1090 --exec dump1090 -- --net --modeac --fix --enable-agc
    echo "Stopping dump1090"
    # kill application you want to stop
    killall dump1090
    echo "Usage: /etc/init.d/dump1090 {start|stop}"
    exit 1

exit 0 

The upper script will be placed in the directory /etc/init.d and after it is marked as executable (e.g. via sudo chmod +x /etc/init.d/dump1090) then the service can be started and stopped with the commands. The attendive reader will recognise that program is not started directly, but with the start-stop-daemon program. The reason behind this is that the start-stop-daemon controls the creation and termination of system-level processes. Using the --exec, --pidfile, --user, and --name options, start-stop-daemon can be configured to find existing instances of a running process. This prevents that the same program will be started twice.

... starting the service ---

$ sudo /etc/init.d/dump1090 start
Starting dump1090

... and stopping the service again ....

$ sudo /etc/init.d/dump1090 stop
Stopping dump1090

The final step is to tie the script to the correct runlevels. In the simplest case this command will work:

$sudo update-rc.d dump1090 defaults

And finally: Here is another interesting article about the start process under ubuntu.

Get Social

(c) 2023, by bytebang e.U. - Impressum - Datenschutz / Nutzungsbedingungen