# Running Programs Automatically on Your Tiny Computer

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/027/431/medium800/raspberry_pi_Screenshot-2015-08-27-15_29_05.png?1440714191)

For projects using a small GNU/Linux system, it's often important that certain code always be running when the computer is on. You can always log in and start a script running by hand once you turn on the power, but this isn't very reliable - after all, the power might flicker, or the system might crash for unrelated reasons. (There's also a good chance you'll be running a system without a monitor or keyboard attached, which can make things that much more complicated - it's much easier to have the right stuff run automatically.)

![](https://cdn-learn.adafruit.com/assets/assets/000/027/432/medium800/raspberry_pi_mus_musculus.png?1440715235)

As an example scenario, I have [a Raspberry Pi system in charge of logging data from my mousetrap](../../../../a-sillier-mousetrap-logging-mouse-data-to-adafruit-io-with-the-raspberry-pi), and I'm about to go on a trip to another continent. The electricity where I live goes out now and then, and I'd like to make sure that my mouse-counting code comes back up on a reboot.

![](https://cdn-learn.adafruit.com/assets/assets/000/027/560/medium800/raspberry_pi_checklist.png?1441143692)

On an Arduino or similar device, the code you write usually just runs shortly after the power comes on, courtesy of a bit of software called a **bootloader**. Linux systems have these too, but what runs by default is the **kernel** , which in turn runs something known as an **init system** that's in charge of starting all sorts of other software to provide important services.

We'll look at how to use two different init systems which are both common in the wild.

 **First, we'll check out SysV-style init on a Raspberry Pi 2**. With roots dating back to early Unix systems, sysvinit was widely used on most Linux distributions until recently, and is still used by the version of Raspbian released in May of 2015, based on Debian Wheezy. It's also similar to mechanisms still used by the [BSD branch of the Unix family tree](https://en.wikipedia.org/wiki/Berkeley_Software_Distribution).

**Next, we'll look at [systemd](https://wiki.freedesktop.org/www/Software/systemd/) on a BeagleBone Black running Debian Wheezy with systemd**. systemd is "a suite of basic building blocks for a Linux system", recently adopted by most of the major distributions, including Debian Jessie (the current stable release of the project). Eventually, Raspbian will probably run systemd too.

Info: 

As always, if you need an introduction to these topics, please check out the rest of our [series on learning Linux with the Raspberry Pi](../../../series/learn-linux-with-raspberry-pi).

# Running Programs Automatically on Your Tiny Computer

## An Example Service: mouse.py

My goal is to have the init system start a script called `mouse.py` every time the Pi boots to multi-user mode (which hopefully will also mean that the network is available).

If you're following along at home, there's a good chance you don't want to mess around with my entire mouse logging project right now, so I'll write a quick Python script for testing purposes (based on [this StackOverflow answer by Nathan Jhaveri](http://stackoverflow.com/a/19440609)).

You can paste or type the code into `~/mouse.py` using Nano and mark it executable:

```auto
nano /home/pi/mouse.py
```

```auto
#!/usr/bin/python
import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write('<:3)~~~')

httpd = SocketServer.TCPServer(("", 80), MyHandler)
httpd.serve_forever()
```

```auto
chmod +x ~/mouse.py
```

All this does is create a very simple web server that, when you visit the Raspberry Pi's network address, returns an ASCII mouse. To test, I'll check my Pi's IP address, start the script, and use `curl` to make sure it's running. (I'm [using tmux to open more than one shell](../../../../an-illustrated-guide-to-shell-magic-typing-less-and-doing-more/use-a-terminal-multiplexer).)

Your IP address will likely be different, but in my case this looks like so:

```auto
ifconfig
sudo ./mouse.py
curl 192.168.0.13
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/535/medium800thumb/raspberry_pi_screencast-2015-08-29-13_30_48.jpg?1448320022)

If&nbsp; you're not on a network, you can just use `localhost` instead:

![](https://cdn-learn.adafruit.com/assets/assets/000/027/536/medium800/raspberry_pi_Screenshot-2015-08-29-13_35_29.png?1440876953)

And if you want to test in a web browser, just enter the Pi's address in the URL bar:

![](https://cdn-learn.adafruit.com/assets/assets/000/027/559/medium800/raspberry_pi_Screenshot-2015-09-01-14_12_05.png?1441138337)

Now that we have an example service, let's talk about how to start it.

# Running Programs Automatically on Your Tiny Computer

## SysV init: Runlevels

![](https://cdn-learn.adafruit.com/assets/assets/000/027/430/medium800thumb/raspberry_pi_screencast-2015-08-27-15_32_37.jpg?1448319746)

## Runlevels and /etc/rc\*.d/
The core idea of sysvinit is something called [runlevels](https://en.wikipedia.org/wiki/Runlevel), which are essentially just a way of organizing a collection of **init scripts** which have to run when the system starts or shuts down. Each runlevel corresponds to a directory in `/etc/`, which in turn contains&nbsp;symlinks to scripts in `/etc/init.d/`.

For historical reasons, there are a lot of runlevels, but a bunch of them aren't really used for anything special on Debian systems. You can read the full details of this [in the Debian manual](https://www.debian.org/doc/manuals/debian-reference/ch03.en.html#_sysv_style_init), but the short version is that the system normally boots to runlevel 2, which is multi-user mode. Adapted from the manual, here's a partial table of levels:

Let's get a list of what's in runlevel 2:

```auto
cd /etc/rc2.d/
ls -l
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/507/medium800thumb/raspberry_pi_screencast-2015-08-28-13_19_52.jpg?1448319781)

`ls -l` gives a **l** ong listing of files, which will helpfully show you if a file is really a link to another file. Again, all of the _actual_ init scripts turn out to live in `/etc/init.d`.

If a file in `/etc/rc*.d/` starts with `K`, it will be invoked by the init system with `[name of script] stop` (K is for kill), and if it starts with `S`, it will be invoked with `[name of script] start`.

Init scripts usually accept (most of) the following command-line parameters:

- `start` - start the service
- `stop` - stop the service
- `status` - check whether the service is running
- `reload` - have the service reload configuration files
- `restart` - stop and start the service

So, for example, you could say `/etc/init.d/ssh restart` to stop and start the SSH service. You often see commands like this in tutorials and HOWTOs.

## The SSH Init Script
As an example, load up `/etc/init.d/ssh` in a text editor and give it a look.

```auto
cd /etc/init.d
nano ssh
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/531/medium800thumb/raspberry_pi_screencast-2015-08-28-15_06_03.jpg?1448319821)

This is actually quite a few lines of code for what seems like a pretty simple task - it just needs to start or stop a program, right? It turns out, though, that there can be a lot of considerations involved in doing that. For example, these rather squirrelly-looking lines...

```auto
test -x /usr/sbin/sshd || exit 0
( /usr/sbin/sshd -\? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0
```

...make sure that `sshd` exists, is executable, and at least _claims_ to be the SSH daemon provided by the OpenSSH project. The rest of the script defines functions for all sorts of housekeeping and sanity checks before it gets to the part where it handles the start/stop/etc. commands in a case statement:

```auto
case "$1" in
  start)
        check_privsep_dir
        check_for_no_start
        check_dev_null
        log_daemon_msg "Starting OpenBSD Secure Shell server" "sshd" || true
        if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
            log_end_msg 0 || true
        else
            log_end_msg 1 || true
        fi
        ;;
  stop)
        log_daemon_msg "Stopping OpenBSD Secure Shell server" "sshd" || true
        if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd.pid; then
            log_end_msg 0 || true
        else
            log_end_msg 1 || true
        fi
        ;;
   
   # a whole bunch of other stuff happens here

esac
```

For one-off projects on the Pi, you almost certainly don't need to exercise this level of caution, but you _will_ want to handle the common commands.

It would be a pain to write a lot of this stuff out from scratch. Fortunately, we have `/etc/init.d/skeleton` to work with. This just provides the "bones" of an init script, and should work with a few minor changes. Next, we'll look at adapting it to run our example `mouse.py`.

# Running Programs Automatically on Your Tiny Computer

## SysV Init: Writing an Init Script for mouse.py

## Copy and Modify the Example Init Script
Start by copying `/etc/init.d/skeleton` to `/etc/init.d/mouselogger`, and marking it executable:

```auto
cd /etc/init.d
sudo cp skeleton mouselogger
sudo chmod +x mouselogger
```

We need the `sudo` here because (like most things in `/etc`) files in `/etc/init.d` are owned by root. (You can imagine what might happen on a system with lots of users if just anyone could muck around in the startup files.)

Next, open this up in Nano:

```auto
nano mouselogger
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/539/medium800thumb/raspberry_pi_screencast-2015-08-31-13_02_28.jpg?1448320069)

I had to change three things. First, the metadata between `BEGIN INIT INFO` and `END INIT INFO` to specifically reference a service called "mouselogger" and provide a description:

![](https://cdn-learn.adafruit.com/assets/assets/000/027/540/medium800/raspberry_pi_Screenshot-2015-08-31-13_09_25.png?1441048174)

Second, the environment variables that the rest of the script uses to do its business. I added `/home/pi` to the path, changed the description to "Mouse logger.", and changed the name to `mouse.py`, as well as emptying the `DAEMON_ARGS` variable:

![](https://cdn-learn.adafruit.com/assets/assets/000/027/541/medium800/raspberry_pi_Screenshot-2015-08-31-13_09_54.png?1441048225)

And lastly, I added `--background` and `--make-pidfile` to the `start-stop-daemon` options in the `do_start()` function:

![](https://cdn-learn.adafruit.com/assets/assets/000/027/542/medium800/raspberry_pi_Screenshot-2015-08-31-14_07_44.png?1441051673)

This ensures that the script is sent to the background instead of running in the foreground after it starts, and creates a file in `/var/run` that contains the process ID of the script.

Here's a [copy of the entire file](https://gist.github.com/brennen/6c0a60e5c46dad146746).

## Test the Script and Install with update-rc.d
You should now be able to run `/etc/init.d/mouselogger` - but first, make sure that `/home/pi/mouse.py` isn't already running.&nbsp; If you have it open in a terminal, you can type **Ctrl-c** to kill the process. Otherwise, use `ps aux | grep mouse.py` to see if it has a running process:

![](https://cdn-learn.adafruit.com/assets/assets/000/027/543/medium800thumb/raspberry_pi_screencast-2015-08-31-14_16_28.jpg?1448320099)

Here, I checked with `ps` and found a copy of the Python interpreter running `mouse.py`, so I killed the corresponding process with `sudo kill 2052`. (2052 is the process id in the second column of the output from `ps`.)

Now you can try starting and stopping the service and testing it out:

```auto
sudo /etc/init.d/mouselogger start
ps aux | grep mouse.py
curl localhost
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/544/medium800/raspberry_pi_Screenshot-2015-08-31-14_21_14.png?1441052484)

```auto
sudo /etc/init.d/mouselogger stop
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/545/medium800/raspberry_pi_Screenshot-2015-08-31-14_22_04.png?1441052535)

Once you're confident that the init script _works_, you can install it in the default runlevels so that it starts at boot time:

```auto
sudo update-rc.d mouselogger defaults
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/546/medium800thumb/raspberry_pi_screencast-2015-08-31-14_24_59.jpg?1448320114)

## Reboot
And now, the moment of truth! Reboot and see what happens...

```auto
sudo reboot
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/548/medium800thumb/raspberry_pi_screencast-2015-08-31-14_27_47.jpg?1448320153)

This part might take a bit, but once you can log back in, it should be simple to test whether `mouse.py` is running:

![](https://cdn-learn.adafruit.com/assets/assets/000/027/547/medium800thumb/raspberry_pi_screencast-2015-08-31-14_29_50.jpg?1448320130)

Success!

Next up, we'll look at doing the equivalent thing with systemd on a BeagleBone Black.

# Running Programs Automatically on Your Tiny Computer

## systemd: Writing and Enabling a Service

Info: 

We have a [whole category of BeagleBone tutorials](../../../../category/beaglebone). I found the specific image I installed on the elinux [BeagleBoneBlack Debian page](http://elinux.org/Beagleboard:BeagleBoneBlack_Debian). Recent editions of the BeagleBone likely come with something very similar installed.

This section assumes that you are logged into your BBB as root.

## Exploring systemd Basics
systemd takes a very different approach from the sysvinit scheme of organizing init scripts into directories by runlevel. Instead, it uses **unit files** to describe **services** that should run, along with other elements of the system configuration. These are organized into named **targets** , like `multi-user.target` and `graphical.target`.

You can list targets on the current system like so:

```auto
sudo systemctl list-units --type=target
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/549/medium800/raspberry_pi_Screenshot-2015-08-31-15_50_15.png?1441057831)

Just running `systemctl` by itself will show you a list of all _active_ units, including configuration for devices, services, filesystem mountpoints, timers, and sockets.

![](https://cdn-learn.adafruit.com/assets/assets/000/027/550/medium800/raspberry_pi_Screenshot-2015-08-31-15_53_59.png?1441058094)

Mostly, systemd units are defined in various files in directories like `/lib/systemd/system`.

If you want to know the status of an existing service, you can use something like `systemctl status foo.service` - for example, let's check up on SSH:

```auto
sudo systemctl status ssh.service
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/551/medium800/raspberry_pi_Screenshot-2015-08-31-16_34_20.png?1441060475)

You might notice something a bit odd here - this status report still mentions `/etc/init.d/ssh`. Isn't that a sysvinit thing? Well, yeah. What is happening is that the system we're on is still a hybrid between old-school and new-school init systems. systemd itself is actually capable of acting as a replacement (mostly) for sysvinit.

This all looks a little daunting, and there are a lot of concepts to untangle if you want to understand everything that's going on (your humble narrator is still quite a ways from this), but just configuring a new service is very little work.

## Writing a Unit File
Let's reuse our example service, `mouse.py`. Run `sudo nano /root/mouse.py`, and paste the following code ( **notice that I've changed the port from 80 to 8888** , so as not to step on the toes of other services already running on the BeagleBone):

```auto
#!/usr/bin/python
import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.wfile.write('<:3)~~~\n')

httpd = SocketServer.TCPServer(("", 8888), MyHandler)
httpd.serve_forever()
```

Then make sure this is executable with `sudo chmod +x /root/mouse.py`. Next, create `/lib/systemd/system/mouselogger.service` and use Nano to paste the following:

```auto
[Unit]
Description=Mouse Logging Service

[Service]
ExecStart=/root/mouse.py
StandardOutput=null

[Install]
WantedBy=multi-user.target
Alias=mouselogger.service
```

Now you can enable your new service:

```auto
sudo systemctl enable mouselogger.service
sudo systemctl start mouselogger.service
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/554/medium800thumb/raspberry_pi_screencast-2015-08-31-17_18_06.jpg?1448320230)

Did it work?

```auto
curl localhost:8888
```

![](https://cdn-learn.adafruit.com/assets/assets/000/027/556/medium800thumb/raspberry_pi_screencast-2015-08-31-18_20_31.jpg?1448008838)

Sure enough! As a last step, you should probably reboot and repeat this test to make _sure_.

# Running Programs Automatically on Your Tiny Computer

## Further Reading

## sysvinit
- &nbsp;[The Debian Manual - The system initialization](https://www.debian.org/doc/manuals/debian-reference/ch03.en.html)
- [Wikipedia: Init](https://en.wikipedia.org/wiki/Init)
- [start-stop-daemon: --exec vs. --startas](https://chris-lamb.co.uk/posts/start-stop-daemon-exec-vs-startas)
- [Getting a Python script to run in the background (as a service) on boot](http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/ "Getting a Python script to run in the background (as a service) on boot")

## systemd
- [Getting Started with systemd on Debian Jessie](https://medium.com/@johannes_gehrs/getting-started-with-systemd-on-debian-jessie-e024758ca63d)
- [systemd for Administrators](http://0pointer.de/blog/projects/systemd-for-admins-1.html)
- [How To Use Systemctl to Manage Systemd Services and Units](https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units)


## Featured Products

### Raspberry Pi 2 Model B Starter Pack - Includes a Raspberry Pi 2

[Raspberry Pi 2 Model B Starter Pack - Includes a Raspberry Pi 2](https://www.adafruit.com/product/2380)
Why not trick out your fresh new board with some&nbsp;accessories? The Pi 2 is a big deal - a big, big deal. &nbsp;It has an upgraded ARMv7 multicore procssor and a full Gigabyte of RAM - meaning you're going to see ~2x the performance on processor-upgrade only and 4x on average for...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/2380)
[Related Guides to the Product](https://learn.adafruit.com/products/2380/guides)
### BeagleBone Black Rev C - 4GB Flash - Pre-installed Debian

[BeagleBone Black Rev C - 4GB Flash - Pre-installed Debian](https://www.adafruit.com/product/1876)
Note: As of May 12, 2014 Adafruit is shipping Rev C. We have discontinued selling Rev B. There are no exchanges or "upgrades" for Rev B to Rev C.  
  
If you liked the BeagleBone Black Rev B, you will love the Rev C! The Rev C still has a blistering 1GHz processor and 512MB...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/1876)
[Related Guides to the Product](https://learn.adafruit.com/products/1876/guides)
### Linux "Tux" Penguin - Skill badge, iron-on patch

[Linux "Tux" Penguin - Skill badge, iron-on patch](https://www.adafruit.com/product/553)
You hacked, modded or made something with Linux! Adafruit offers a fun and exciting "badges" of achievement for electronics, science and engineering. We believe everyone should be able to be rewarded for learning a useful skill, a badge is just one of the many ways to show and...

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/553)
[Related Guides to the Product](https://learn.adafruit.com/products/553/guides)
### Linux "Tux" Penguin - Sticker

[Linux "Tux" Penguin - Sticker](https://www.adafruit.com/product/663)
You hacked, modded or made something with Linux! Adafruit offers a fun and exciting stickers to achievement for electronics, science and engineering. We believe everyone should be able to be rewarded for learning a useful skill, a sticker is just one of the many ways to show and share.<br...></br...>

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/663)
[Related Guides to the Product](https://learn.adafruit.com/products/663/guides)

## Related Guides

- [Arm-based IoT Kit for Cloud IoT Core - Getting Started](https://learn.adafruit.com/raspberry-pi-3-and-sensor-kit-for-google-cloud-iot-core.md)
- [Programming Microcontrollers using OpenOCD on a Raspberry Pi](https://learn.adafruit.com/programming-microcontrollers-using-openocd-on-raspberry-pi.md)
- [Adafruit Raspberry Pi Educational Linux Distro](https://learn.adafruit.com/adafruit-raspberry-pi-educational-linux-distro.md)
- [Using the BMP085/180 with Raspberry Pi or Beaglebone Black](https://learn.adafruit.com/using-the-bmp085-with-raspberry-pi.md)
- [MCP4725 12-Bit DAC with Raspberry Pi](https://learn.adafruit.com/mcp4725-12-bit-dac-with-raspberry-pi.md)
- [Matrix and 7-Segment LED Backpack with the Raspberry Pi](https://learn.adafruit.com/matrix-7-segment-led-backpack-with-the-raspberry-pi.md)
- [Adafruit 16x2 Character LCD + Keypad for Raspberry Pi](https://learn.adafruit.com/adafruit-16x2-character-lcd-plus-keypad-for-raspberry-pi.md)
- [Adafruit NFC/RFID on Raspberry Pi](https://learn.adafruit.com/adafruit-nfc-rfid-on-raspberry-pi.md)
- [Touch Pi: Portable Raspberry Pi](https://learn.adafruit.com/touch-pi-portable-raspberry-pi.md)
- [Raspberry Pi as an Ad Blocking Access Point](https://learn.adafruit.com/raspberry-pi-as-an-ad-blocking-access-point.md)
- [Adafruit CH334F Mini USB Hub Breakouts](https://learn.adafruit.com/adafruit-ch334f-mini-4-port-usb-hub-breakout.md)
- [Nokia 5110/3310 LCD Python Library](https://learn.adafruit.com/nokia-5110-3310-lcd-python-library.md)
- [Raspberry Pi Pipboy 3000](https://learn.adafruit.com/raspberry-pi-pipboy-3000.md)
- [Using a 5V Stepper Motor with the RasPiRobot Board V2](https://learn.adafruit.com/using-a-5v-stepper-motor-with-the-raspirobot-board-v2.md)
- [Raspberry Pi radio player with touchscreen](https://learn.adafruit.com/raspberry-pi-radio-player-with-touchscreen.md)
