Daemonize that Python script!

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:

service --status-all

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:
http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/

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

Logging

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:

http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-background-as-a-service-on-boot/

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:

https://github.com/LarsBergqvist/RemoteControlled_Outlets

 

 

 

Advertisements

One thought on “Daemonize that Python script!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s