Linux Systemd Services

Systemd is a fairly recent part of linux operating system – RedHat started developing systemd in 2010 and it was added to version 15 of ubuntu linux back in the year 2015. It is responsible for booting the system correctly and maintaining all its services in its proper state.

Basically, systemd is a successor of init scripts used on older linux systems.

systemd logo

Why should we use systemd services?

Systemd has a lot of advantages which can be very helpful in case of serious issues with the system of service malfunctioning. Some of them concern the automatic checks of the state and restart the processes in case of failure. They limit used memory/cpu usage in case of some rogue process trying to overload the system because of an issue or furthermore checks for dependencies so you cannot get stuck in a wait loop with non-responsive system. It is also much easier to check output of each service, but more about that later. Services have a lot of options you can go for and use, for example instead of crons.

Where can we find such services?

Every service needs to have “servicefile” describing that service. There are 3 directories with files for all services in the system. Of course, you can create services whenever you want to and in one of these directories just create symlinks to your services located somewhere else.

  • /etc/systemd/system/
  • /lib/systemd/system/
  • /run/systemd/system/

Let’s create some!

Creating script that should be executed

At first, we need to create some script or a program which will be performed in our service. We need it to work without stopping or failing in case of issues. The following should be good enough.

#!/bin/bash
echo "Starting up..."
FILE=/var/tmp/logfile.txt
echo "Started, logging time..."
while true; do
  if [-f "$FILE"]; then
    date '+%Y-%m-%d%H:%M:%S' >> "$FILE";sleep 10
  else
    echo "Logfile not present!"; exit 1
  fi
done

Creating servicefile

When you know what you want to run you can finally create the service itself. Create a file with your service name in one of the 3 directories mentioned before. I named mine ourService.service. Service extension means that it is a service while the first part is the name of the service. You need to at least specify how to start our command and how to stop it. It is also nice to have a description. WantedBy states when it should be started on the system boot, more about that may come in a more advanced article in the future. For now, you can just insert it there. The content should look similar to this:

[Unit]
Description=Our beautiful service

[Service]
ExecStart=/usr/bin/ourCommand
ExecStop=/usr/bin/killall ourCommand

[Install]
WantedBy=multi-user.target

Enabling, starting, and editing the service

Now that you know what you want to run and have created servicefile, you can finally launch it. You can do so by doing the following:

systemctl start ourService

Now your service should be launched and you can check that by inserting this:

systemctl status ourService

If you did everything correctly, your service is running all good and you can enjoy a very satisfying view similar to this:

 ● ourService.service - Our beautiful service
    Loaded: loaded (/lib/systemd/system/ourService.service; disabled; vendor preset: enabled)
    Active: active (running) since Sun 2020-03-01 21:36:04 CET; 22min ago
   Main PID: 13726 (ourCommand)
   CGroup: /system.slice/ourService.service
           ├─13726 /bin/bash /usr/bin/ourCommand
           └─16156 sleep 10
 Mar 01 21:36:04 server1 systemd[1]: Started ourService.service.
 Mar 01 21:36:04 server1 ourCommand[13726]: Starting up...
 Mar 01 21:36:04 server1 ourCommand[13726]: Started, logging time...

Also, in case you used ourCommand created before, you can see the changes in the logfile.

When you edit the existing service, you need to do the following to fetch the system a new servicefile:

systemctl daemon-reload

It is also useful when your service undergoes a vast failure and you need to reset counters/timers for service restarts. How to set up restart on failure and reset timers will be in our future more advanced article about this topic.

After creating the working service, you will probably need it to start immediately after the startup of the system. You can do that by using this:

systemctl enable ourService

And similarly when you don’t want it to start on startup:

systemctl disable ourService

Diagnosis of services

Honestly, in most cases things are not working as straight as here with our super-simple service. It can also malfunction because of certain issues anywhere in the system. Then you need to find out what’s wrong. The following command is the best as it shows you the last output of your service:

journalctl -xe -u ourService

Let’s try it, I removed the logfile used in ourCommand and ourService will fail the next time it checks if there is our logfile in the desired directory.

Mar 01 21:36:04 server1 ourCommand[13726]: Starting up...
Mar 01 21:36:04 server1 ourCommand[13726]: Started, logging time...
Mar 01 22:02:45 server1 ourCommand[13726]: Logfile not present!
Mar 01 22:02:45 server1 systemd[1]: ourService.service: Main process exited, code=exited, status=1/FAILURE
Mar 01 22:02:45 server1 killall[16494]: ourCommand: no process found
Mar 01 22:02:45 server1 systemd[1]: ourService.service: Control process exited, code=exited status=1
Mar 01 22:02:45 server1 systemd[1]: ourService.service: Unit entered failed state.
Mar 01 22:02:45 server1 systemd[1]: ourService.service: Failed with result 'exit-code'.

Great! Here is the full output and info on how the systemd coped with it. You can clearly see the full output of ourCommand saying there is no logfile.

Hope we helped you with the basics of creating a new service. In future there will be a more advanced article with advanced service options setup and some showcases on how you can use services with timers instead of cron. If you are interested, please subscribe to our newsletter and don’t miss it!

The original autor: Jakub, DevOps Engineer, cloudinfrastack