Markdown source

#How to use systemd for applications start

<abstract>
On the latest Debian distributions is installed by default systemd instead of sysvinit as initialization system.
This article illustrates pratically how to use it. 
</abstract>

To launch a script at startup a proper service file have to be created and added to the systemd.

Let's create a service file for our myapplication.py program. Create as root
a file called __myapplication.service__ in __/lib/systemd/system__ directory.

	sudo nano /lib/systemd/system/myapplication.service
	
then save inside it this content:	

	[Unit]
	Description=My Application as Service
	After=network.target
	
	[Service]
	Type=idle
	ExecStart=/usr/bin/python /home/acmesystems/myapplication.py
	Restart=always
	User=pi
	
	[Install]
	WantedBy=multi-user.target

Next systemd has to be configured, enabling the service so at the next reboot it will be started automatically.
First off, though, the systemd itself has to be reloaded in order to detect the new service definition:

	sudo systemctl daemon-reload

Next, enable the service

	sudo systemctl enable myapplication.service

Check if it is enabled:

	sudo systemctl list-unit-files | grep enabled

Of course, it can be started manually just now:

	sudo systemctl start myapplication.service

The PID (process id) can be now checked:

	ps -ef | grep myapplication
	pi         817     1  0 09:19 ?        00:00:00 /usr/bin/python myapplication.py

it is 817 (the number will be different in your case).
Please note that it has been started from systemd process, in fact the PPID (parent process id) is <b>1</b>.

### Test what happens if the program crashes and/or terminates.

In order to simulate a crash, we kill it manually:

	sudo kill 817

Now we can check it was restarted looking again  to the PID (process id):

	ps -ef | grep myapplication
	pi        1037     1  0 09:19 ?        00:00:00 /usr/bin/python myapplication.py

it is now 1037 (PPID always <b>1</b>), so, as it is different, that means has been restarted automatically after the kill.

### How to see full log from systemctl status service ?

Use the journalctl command, as in:

	journalctl -u myapplication.service

## How to start a script right before shutdown

This is an example on how to start a Python script called shutdown.py at shutdown:

	[Unit]
	Description=Send a message on the Oled at shutdown

	[Service]
	Type=oneshot
	RemainAfterExit=true
	WorkingDirectory=/home/pi/Adafruit_Python_SSD1306/examples
	ExecStop=/usr/bin/python shutdown.py
	User=pi
	
	[Install]
	WantedBy=multi-user.target
	
Save is as __/lib/systemd/system/oled.service__

Reload the new service definition:

	sudo systemctl daemon-reload
 
Enable the new service:

	sudo systemctl enable oled.service
	
Then shutdown:

	sudo halt

### Links

* Script di esempio: [shutdown.py](./shutdown.py)
* Font usato dallo script di esempio: [wonder.ttf](./wonder.ttf)
* [Dove ho trovato le info](https://unix.stackexchange.com/questions/39226/how-to-run-a-script-with-systemd-right-before-shutdown)
* [Oled di Adafruit usato nell'esempio](https://www.adafruit.com/product/661)

## SystemV the old way

A few pieces of old way are still present and working as for example __/etc/rc.local__ where 
all the applications that implement the system functionality are started.  

A typical __rc.local__ contains:

	cat /etc/rc.local
	
	#!/bin/sh -e
	#
	# rc.local
	#
	# This script is executed at the end of each multiuser runlevel.
	# Make sure that the script will "exit 0" on success or any other
	# value on error.
	#
	# In order to enable or disable this script just change the execution
	# bits.
	#
	# By default this script does nothing.
	
	cd /home/acmesystems
	/usr/bin/nohup /usr/sbin/python myapplication.py &
	exit 0

In this example a Python program is started from application's home directory, and left in background (using the trailing ampersand). 
That works passably well till our python application never crashes: in such unfortunate case,  our system only chance
has, in order to regain the lost functionality, is to be manually restarted by user (probably cycling the power...).

Usually, the quick and dirty solution suggested is to add our application to the __/etc/inittab__ file, specifyng a __respawn__ 
in the line:

	id:2345:respawn:/bin/sh /path/to/application/startup

in such case startup must be a proper script able to start out application (and probably it could be convenient to reuse 
this script as is even in /etc/rc.local).


## Links

* [Understanding Systemd Units and Unit Files](https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files)
* [Systems tutorial on Linux Magazine](http://www.linux-magazine.com/Issues/2017/200/Tutorials-Systemd)
* [How To Use Systemctl to Manage Systemd Services and Units](https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units)

@include='bio_andrea_montefusco'
@include='bio_sergio_tanzilli'