This post builds on a previous experiment where I made a remote control app for my outlets with a Raspberry Pi, Python/Flask and AngularJS. For the backend to be really useful, I want to make it behave as a service in Linux. It should start automatically after a reboot and there should be some control mechanism for manually starting, stopping and viewing the status of the service. There should also be a proper logging in place.
Services in Raspbian
Handling services in Raspbian/Debian requires a few commands: service, update-rc.d and systemctl. To display the status of all registred services, you can use the service command:
It will show a list like:
[ + ] alsa-utils [ + ] avahi-daemon [ + ] bluetooth [ - ] bootlogs [ - ] bootmisc.sh [ - ] checkfs.sh [ - ] checkroot-bootclean.sh [ - ] checkroot.sh [ + ] console-setup ...
The prefixes mean:
[+] - the service is running [-] - the service is not running
And for checking a specific service:
service [ServiceName] status
A service can be started, stopped or restarted with the appropriate switches:
sudo service [ServiceName] start sudo service [ServiceName] stop sudo service [ServiceName] restart
Creating a new service in Raspbian
An application can be started as a daemon process with the start-stop-daemon command. But as this command has a rather intricate argument list, it is better to create a bash script that simplify the usage (this will also allow auto start when booting). For example, to start a daemon process we want to specify the program (with possible arguments) to run, what user that should run the process and create a PID file so that the process can be tracked, the full argument list would look something like this:
start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
Not something that you would like to type many times.
Instead, you can use a bash file as described by Stephen C Phillips in this excellent tutorial:
The init file for my Flask application would look something like this:
Note: to get the Python script started with this bash file, you need to add execution rights on the Python file and also on the bash script file. In my case:
chmod 777 remotecontrol.py sudo chmod 777 /etc/init.d/remotecontrol.sh
If you put the bash script in the /etc/init.d/ folder you can use the update-rc.d command to add the service for autostart when booting. For example:
sudo update-rc.d remotecontrol.sh defaults
This will add make the application run at the default run level (see https://wiki.debian.org/RunLevel).
To remove the service from autostart:
sudo update-rc.d -f remotecontrol.sh remove
If you change the bash script, you can reload it with the systemctl command:
sudo systemctl daemon-reload
As the application now runs in the background, we can not see any messages that are printed out. Stephen C Phillips has made a very useful logging example in his blog post:
It uses the Python Logging library and is easily adapted for any Python application.
I have updated the code for my Remote Outlet application so that it uses a similar logger. With the Python script now running as a background service, the tracing and any other output are routed to the log file in /tmp/remotecontrol.log.
The GitHub repository has been updated with the new code that includes service handling and logging: