#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>

The original version of this article is available on: <http://www.tanzolab.it/systemd>

## Create a service

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

Let's create for example a service file to launch a Python program called <code>blink.py</code>. Create as root
a file called <code>blink.service</code> in <code>/lib/systemd/system</code> directory.

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

	[Unit]
	Description=Blinking led
	After=network.target
	
	[Service]
	Type=idle
	ExecStart=/usr/bin/python /root/blink.py
	Restart=always
	User=root
	
	[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 blink

Check if it is enabled:

	systemctl list-unit-files | grep enabled

Of course, it can be started manually just now:

	sudo systemctl start blink

The PID (process id) can be now checked:

	ps -ef | grep blink
	pi         817     1  0 09:19 ?        00:00:00 /usr/bin/python blink.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:

	kill 817

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

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

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

## Use the systemd logging system

To check what is doing your service launch this command:

	journalctl -f blink

It is possible, of course, to add our own messages to this log. In Python, for example,
install the __python-systemd__ package:

	apt-get update
	apt-get install python-systemd
	
add these lines to your code:

	import logging
	from systemd.journal import JournalHandler
	
	log = logging.getLogger('blink')
	log.addHandler(JournalHandler())
	log.setLevel(logging.INFO)
	
	log.info("Blinking led started")

Open another terminal and launc journalctl with follow option (-f):

	journalctl -u -f blink
	...
	May 13 11:49:24 roadrunner systemd[1]: Started Blinking led.
	May 13 11:49:25 roadrunner /root/blink.py[18081]: Blinking led started

## Create a timer for your service

<abstract>
It is possible to use the systemd timers to launch a service instead of using cron
</abstract>

### Example 1: Run a service every hour

Create a systemd service file in <code>/lib/systemd/system/blink.service</code> with this contents:

	[Unit]
	Description=Blinking led
	
	[Service]
	WorkingDirectory=/root
	ExecStart=python blink.py
	User=root

Create a systemd timer file for this service in <code>/lib/systemd/system/blink.timer</code> with this contents::

	[Unit]
	Description=Runs blink.py every hour
	
	[Timer]
	# Time to wait after booting before we run first time
	OnBootSec=10min
	# Time between running each consecutive time
	OnUnitActiveSec=1h
	Unit=blink.service
	
	[Install]
	WantedBy=multi-user.target

Reload the service definitions:

	sudo systemctl daemon-reload

Then is your are using the same file of previous example disable the blink.service and enable just the blink.timer
to start it after the bootstrap:

	sudo systemctl disable blink.service
	sudo systemctl enable blink.timer
	
Let's try it now:	

	sudo systemctl start blink.timer

### Example 2: Run a service daily

	[Unit]
	Description=Runs blink.py daily at midnight
	
	[Timer]
	OnCalendar=*-*-* 00:00:00
	Persistent=True	
	Unit=blink.service
	
	[Install]
	WantedBy=multi-user.target

Changing the __OnCalendar__ parameter is possible to start the blink.service 
in a lot of different way:

	Minimal form                   Normalized form
	Sat,Thu,Mon-Wed,Sat-Sun    ==> Mon-Thu,Sat,Sun *-*-* 00:00:00
	Mon,Sun 12-*-* 2,1:23      ==> Mon,Sun 2012-*-* 01,02:23:00
	Wed *-1                    ==> Wed *-*-01 00:00:00
	Wed-Wed,Wed *-1            ==> Wed *-*-01 00:00:00
	Wed, 17:48                 ==> Wed *-*-* 17:48:00
	Wed-Sat,Tue 12-10-15 1:2:3 ==> Tue-Sat 2012-10-15 01:02:03
	*-*-7 0:0:0                ==> *-*-07 00:00:00
	10-15                      ==> *-10-15 00:00:00
	monday *-12-* 17:00        ==> Mon *-12-* 17:00:00
	Mon,Fri *-*-3,1,2 *:30:45  ==> Mon,Fri *-*-01,02,03 *:30:45
	12,14,13,12:20,10,30       ==> *-*-* 12,13,14:10,20,30:00
	mon,fri *-1/2-1,3 *:30:45  ==> Mon,Fri *-01/2-01,03 *:30:45
	03-05 08:05:40             ==> *-03-05 08:05:40
	08:05:40                   ==> *-*-* 08:05:40
	05:40                      ==> *-*-* 05:40:00
	Sat,Sun 12-05 08:05:40     ==> Sat,Sun *-12-05 08:05:40
	Sat,Sun 08:05:40           ==> Sat,Sun *-*-* 08:05:40
	2003-03-05 05:40           ==> 2003-03-05 05:40:00
	2003-03-05                 ==> 2003-03-05 00:00:00
	03-05                      ==> *-03-05 00:00:00
	hourly                     ==> *-*-* *:00:00
	daily                      ==> *-*-* 00:00:00
	monthly                    ==> *-*-01 00:00:00
	weekly                     ==> Mon *-*-* 00:00:00
	*:20/15                    ==> *-*-* *:20/15:00

* [Original article](https://www.certdepot.net/rhel7-use-systemd-timers/)

### Check the list of timers

	systemctl list-timers --all
	...
	NEXT                          LEFT     LAST                          PASSED       UNIT                         ACTIVATES
	Mon 2018-05-14 00:00:00 CEST  10h left Sun 2018-05-13 13:14:44 CEST  2min 17s ago blink.timer                  blink.service
	Mon 2018-05-14 10:38:28 CEST  21h left Sun 2018-05-13 10:38:28 CEST  2h 38min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
	n/a                           n/a      n/a                           n/a          apt-daily-upgrade.timer      apt-daily-upgrade.service
	n/a                           n/a      n/a                           n/a          apt-daily.timer              apt-daily.service

### Links

* [systemd.timer configuration](https://www.freedesktop.org/software/systemd/man/systemd.timer.html)
* [How to Use Systemd Timers](https://jason.the-graham.com/2013/03/06/how-to-use-systemd-timers/)


## 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=/root
	ExecStop=/usr/bin/python shutdown.py
	User=root
	
	[Install]
	WantedBy=multi-user.target
	
Save is as <code>/lib/systemd/system/oled.service</code>

Reload the new service definition:

	systemctl daemon-reload
 
Enable the new service:

	systemctl enable oled.service
	
Then shutdown:

	halt

## How to start a script into the text console

	[Unit]
	Description=my_python_script
	After=multi-user.target
	Conflicts=getty@tty1.service
	
	[Service]
	Type=simple
	ExecStart=/usr/bin/python3 /home/pi/my_python_script.py
	StandardInput=tty-force
	StandardOutput=inherit
	StandardError=inherit
	
	[Install]
	WantedBy=multi-user.target  

### Links

* [Original article](https://unix.stackexchange.com/questions/39226/how-to-run-a-script-with-systemd-right-before-shutdown)
* [Display used](https://www.adafruit.com/product/661)
* [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)
* [https://www.mauras.ch/systemd-run-it-last.html](https://www.mauras.ch/systemd-run-it-last.html)
* <https://raspberrypi.stackexchange.com/questions/103616/boot-into-text-console-and-auto-run-script>
@include='bio_tanzilli'
