Autostart python scripts on boot with systemd
Recently I tried to run one of my Python projects on boot, and I was faced with the problem on how to do this elegantly on current Debian based Linux distros. After a bit of googling I found a quick and reliable way by utilizing a systemd service.
Never mess again with strangle rc.local
files or crontab @reboot
solutions.
With systemd services you can also reliably access logs and see the status of your process. This is especially useful for Python projects on things like a Raspberry Pi which you use headless and want to start your script as soon as it boots.
How To
Replace <YOUR-NAME>
with a name descriptive of your project. Make it memorable because you probably have to remember it at some point.
Find out the path to your python runtime with which
which python
This will return something like this
/usr/bin/python
, use this later as<YOUR-PYTHON-PATH>
Create a service via:
sudo systemctl --force --full edit <YOUR-NAME>.service
And paste
[Unit] Description=<(Optional) Description of your project> After=network.target [Service] ExecStart=<YOUR-PYTHON-PATH> <PATH-TO-YOUR-SCRIPT>.py [Install] WantedBy=multi-user.target
Save it and reload all Systemd services via
sudo systemctl daemon-reload
Enable autostart on boot of your new service:
sudo systemctl enable <YOUR-NAME>.service
Variations
Time of start
The previous example assumes you want your script to start after the network interfaces were initialized and the OS is ready to use. You can change this behaviour by changing the values of the After=
and WantedBy=
parameters in the service file.
Virtual Environments
You can also start python scripts utilizing virtual environments this way by explicitly using the path to the python binary of your virtual environment like this:
ExecStart=/home/<PATH-TO-PROJECT>/venv/bin/python <PATH-TO-YOUR-SCRIPT>.py
Changing working directory
You can also change the working directory for your service before you start your script. This is especially useful if you reference
relative paths in your code like machine learning models or asset folders.
You can do this by adding a WorkingDirectory
property to the service. Be aware that you
still have to use absolute paths to reference your python executable and your script.
[Service]
WorkingDirectory=/home/user/<PATH-TO-PROJECT>
ExecStart=/home/<PATH-TO-PROJECT>/venv/bin/python <PATH-TO-YOUR-SCRIPT>.py
Execute as user or group
Lastly you can execute your python script as specific Linux user and/or group e.g. as user “pi” if there are some specific permissions requiring this. For this to work you specify a user or group in the service part of the file. This is an example on how to do this for the user pi:
[Unit]
Description=<(Optional) Description of your project>
After=network.target
[Service]
ExecStart=<YOUR-PYTHON-PATH> <PATH-TO-YOUR-SCRIPT>.py
User=pi
Group=pi
[Install]
WantedBy=multi-user.target
Managing the running script
Stop & Restart
You can stop your service by executing:
sudo systemctl stop <YOUR-NAME>.service
The same goes for restarting it via:
sudo systemctl restart <YOUR-NAME>.service
Status & Basic logs
You can check if your service is running or crashed by typing:
sudo systemctl status <YOUR-NAME>.service
This will also show you the last few lines logged by your script (e.g. print statements).
Disable autostart again
You can disable autostart for your new service at any time by typing:
sudo systemctl disable <YOUR-NAME>.service