Let’s say you have developed a super program running on your Raspberry Pi 4 board. But here’s the problem: to start it you always have to power on the board, log in (with a screen and keyboard or via ssh), and start your program. How could you make your Raspberry Pi 4 program start on boot?
Fortunately, there are some solutions to your problem. The most complete one is systemd. Systemd is simply a standard Linux process to control which program should start when the operating system boots. Good news, it’s already installed for you if you use Raspbian/Noobs/Ubuntu for RPi.
In this tutorial I’ll show you step by step how to use systemd to make your Raspberry Pi 4 program start on boot.
Note: this also works for Raspberry Pi 3 boards.
Ready? Let’s go!
Create the Raspberry Pi 4 program which will start on boot
To be able to start a program, you first need to have one. Let’s create a simple Python program in your home repository. Note that I’ll use “/home/pi” as the home repository during all the tutorial, so you’ll have to replace “pi” with your username if you changed it from the default one.
You are learning how to use Raspberry Pi to build your own projects?
Check out Raspberry Pi For Beginners and learn step by step.
Let’s say we want to make sure a given file exists when we boot the Raspberry Pi 4.
In your home directory, create a Python file and make it executable.
$ cd ~ $ touch ensure-file-exists.py $ chmod +x ensure-file-exists.py
Now, edit the file with whatever text editor you prefer (Nano, Vim, Emacs, etc). Here’s the content of the script:
#!/usr/bin/env python3 if __name__ == '__main__': with open("/home/pi/required_file", "w") as f: f.write("OK\n")
It’s pretty basic. We just create a file with the write mode, and write “OK” inside. If the file doesn’t exist, it will be created. Note that by using
with, we don’t need to write the code to close the file.
Now, save and exit. Let’s run the program to check if it’s working correctly (it should!):
$ ls Desktop Documents Downloads ensure-file-exists.py MagPi Music Pictures Public Templates Videos $ python3 ensure-file-exists.py $ ls Desktop Documents Downloads ensure-file-exists.py MagPi Music Pictures Public required_file Templates Videos $ cat required_file OK
Now remove the file that was created by your script.
pi@raspberrypi:~ $ rm required_file
Add a systemd service
Now that we have a script, and we know it’s working correctly, let’s create a new systemd service.
$ cd /lib/systemd/system $ sudo touch ensure-file-exists.service
All services will be located in the “/lib/systemd/system” folder. On boot, systemd will look after all enabled services and start them.
Now, edit this file (with sudo) and write the following:
[Unit] Description=Ensure file exists on boot After=multi-user.target [Service] ExecStart=/usr/bin/python3 /home/pi/ensure-file-exists.py User=pi [Install] WantedBy=multi-user.target
This is a very basic template for writing a systemd service. Here’s what each field means:
- Description: not important, just write anything you want here.
- After: this controls when the service should be triggered. Basically, “multi-user.target” means that the service will be triggered once the multi-user environment is available. Note that this will not wait until the login or desktop screen appears.
- ExecStart: the actual command line to execute. Here we start the Python script that we’ve created in the home repository. Note that it’s important to use an absolute path for the script path.
- User: if we don’t specify the user, then the program will be executed as root user. What could be the problem here? Well, the Python script we execute is creating a file. If the root user launches the Python script, then the file will be created by the root user, not by the “pi” user. So, the “pi” user might encounter permission issues when trying to modify/remove this script later on.
- WantedBy: as we specified “multi-user.target” before, we need to also write it here.
The service is now complete! You can now save and exit.
Enable the systemd service
If you don’t do anything else, well… Nothing will happen. You need to enable the service so systemd will run it on boot.
$ sudo systemctl daemon-reload $ sudo systemctl enable ensure-file-exists.service Created symlink /etc/systemd/system/multi-user.target.wants/ensure-file-exists.service -> /lib/systemd/system/ensure-file-exists.service.
Once done, your service will be started on every Raspberry Pi boot!
To check if your service is enabled, use this command:
$ sudo systemctl list-unit-files | grep ensure-file-exists ensure-file-exists.service enabled
This tells you that 1. The “ensure-file-exists” service exists, and 2. it is enabled.
If you want to disable the service, simply do:
$ sudo systemctl disable ensure-file-exists.service Removed /etc/systemd/system/multi-user.target.wants/ensure-file-exists.service.
Test the service to make the Raspberry Pi 4 program start on boot
To test the service, simply reboot your Raspberry Pi 4, and check if the “required_file” was created in your home repository.
There is also another way to test the correct execution of the service. As you saw before, you can enable/disable a service with
systemctl enable and
systemctl disable. Well, you can start (and stop, if your program runs indefinitely) the service with
systemctl start and
$ sudo systemctl start ensure-file-exists.service
This will start your newly created service just as when the Raspberry Pi boots. Very handy for testing without having to reboot every time. Also, if you want to always start a program on boot and stop it manually when you want to, the
systemctl stop function is perfect for that.
When to use systemd with Raspberry Pi?
Note that systemd is much more complex than that, I just showed you here a very basic example – though it’s all that you need to know in order to make any Raspberry Pi 4 program start on boot.
So, what are some good examples of when you’ll have to use this?
- Web server: once you have developed the program, you can make a headless server accessible whenever you boot your Raspberry Pi.
- Robot: a Raspberry Pi board is really small and perfect for being embedded on a robot. With systemd you can make your robot start directly when you power it on.