Raspbian Service creation from python script
Not intended to be a tutorial, there are plenty of those with much better explanations than I can whip together out there on the nets. This is another page from my notebook of commands that I am endlessly re-Googling.
Create a unit file:
cd /lib/systemd/system/
sudo nano sample.service
...or, if you prefer vim, use could always use vi instead of nano
Fill it with:
[Unit]
Description=My Sample Service
After=multi-user.target
[Service]
Type=idle
ExecStart=/usr/bin/python3 /home/pi/sample.py
[Install]
WantedBy=multi-user.target
I'm assuming you are using / have installed python3
This is a very bare bones unit file, there is much more we can do with this, see at the bottom of this post
Set the permissions of sample.service:
sudo chmod 644 /lib/systemd/system/sample.service
Every time you make any kind of change to any unit file:
sudo systemctl daemon-reload
You must enable the service if you want it to start automatically on boot:
sudo systemctl enable sample.service
you will need repeat this action if/when you rename the service / init file
Reboot the Pi:
sudo reboot
Once a service has been installed:
sudo service <xyz> start
sudo service <xyz> stop
sudo service <xyz> restart
sudo service <xyz> status
all credit goes to:
https://www.dexterindustries.com/howto/run-a-program-on-your-raspberry-pi-at-startup/
https://github.com/torfsen/python-systemd-tutorial
That unit file, what else can we do with it?
Restart service on failure and run permissions
- I want the service to restart automatically if the script crashes for any reason
- If the script needs sudo permissions, we can run the service as root
[Unit]
Description=Simple explanation of Service
After=network.target
[Service]
Type=idle
SyslogIdentifier=SampleService
ExecStart=/usr/bin/python3 /home/pi/sample.py
Restart=on-failure
RestartSec=20
User=root
Group=root
[Install]
WantedBy=multi-user.target
Syslogging
I am currently (November 2019) leaving print statements in my python scripts that describe the actions executed, this helps help me identify exactly what is working and NOT working while I construct and run the script.
When we run the script as a service using systemd, these print statements do not appear in the terminal. Below are 2x ways we can inject these print statements into the system log.
method 1 - syslog function
Within the python script, import the syslog function from the syslog module, then anytime we want something to be printed to the syslog, we can.
from syslog import syslog
...
syslog(f"print string to the syslog, with {var1} and {var2}:")
In this example I am using f-String syntax for the string to be printed within the syslog
this is exactly the same as writing:
syslog("print string to the syslog, with " + str(var1) + " and " + str(var2) + ":")
method 2 - print to syslog
This is a less controllable solution, a more blunt approach.
Add the following to the init service file.
[Service]
...
StandardOutput=syslog
StandardError=syslog
Environment=PYTHONUNBUFFERED=1
The problem with this approach is that everything that would normally appear in the terminal output will be printed in the syslog, including stuff that you might not want to see in there.