How to create a systemd service?

Published: Fri 12 June 2020
By evpo

In OS.

Running process

We will use a Minecraft server as an example. This is a Java application. It should start when the machine boots up and it stops gracefully when the service is stopped. The service name will be minecraft.

Create a text file at the following location: /etc/systemd/system/minecraft.service

Below is the content of the file:

[Unit]
Description=Minecraft
After=network.target

[Service]
WorkingDirectory=/home/minecraft/Minecraft_Server
ExecStart=/usr/bin/java -Xms1G -Xmx1G -jar server.jar nogui
User=minecraft
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Most of those settings are self-descriptive. When the service stops, it sends SIGTERM to the Java process. Minecraft handles that signal and exits with exit code 143. In this case the exit code is expected. For that reason, it is assigned to the success status.

Start and stop commands

Our next service is BuildBot. To start BuildBot we call buildbot start. The command starts BuildBot in the background and returns execution back to us immediately. To stop the daemon we call buildbot stop. The commands will be executed in two scripts called start-bbot.sh and stop-bbot.sh respectively.

[Unit]
Description=BuildBot
After=network.target

[Service]
Type=oneshot
WorkingDirectory=/home/bbot/ve/bb-worker
RemainAfterExit=true
ExecStart=start-bbot.sh
ExecStop=stop-bbot.sh

[Install]
WantedBy=multi-user.target

oneshot instructs our service that it will execute the script and exit. RemainAfterExit will keep the service in running state after the script in ExecStart exits.

Running script

This service is a bash script running a main loop with sleep. The script receives kill signal when it needs to stop.

[Unit]
Description=Check and reconfigure
After=network.target

[Service]
ExecStart=/home/bbot/bin/bbot-check-and-reconfigure.sh
ExecStop=/usr/bin/kill -s SIGTERM $MAINPID
TimeoutStopSec=45
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

The script we are running is below:

1
2
3
4
5
6
7
8
9
#!/usr/bin/env bash

while true; do
    if [[ -f "${HOME}/new_config.flag" ]] ; then
        reconfigure-bbot.sh
    fi
    echo "sleep..."
    sleep 10
done

Start a script and forget

This script adds rules to iptables. It's done once at bootup and we don't need to stop or monitor this service

[Unit]
Description=forwarding service
After=network.target

[Service]
ExecStart=/bin/bash /var/forwarding/forwarding
WorkingDirectory=/var/forwarding/
Type=simple
User=root
Group=root

[Install]
WantedBy=multi-user.target

Systemd user service

To create a user service make the following directory first:

mkdir -p ~/.config/systemd/user

The service file ~/.config/systemd/user/ssh-agent.service:

[Unit]
Description=SSH agent service

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/bash ./start.sh
ExecStop=/bin/bash ./stop.sh
WorkingDirectory=/home/john/sshagentd

[Install]
WantedBy=default.target

Then the start and stop files will be as below:

start.sh:

1
2
3
4
#!/bin/bash
ssh_agentd_info_file=/var/tmp/${USER}_ssh_agentd_info
echo writing to ${ssh_agentd_info_file}
/usr/bin/ssh-agent -s > ${ssh_agentd_info_file}

stop.sh:

1
2
3
4
5
#!/bin/bash
ssh_agentd_info_file=/var/tmp/${USER}_ssh_agentd_info
source ${ssh_agentd_info_file}
/usr/bin/ssh-agent -k
rm ${ssh_agentd_info_file}

.bashrc will need an extra line:

source /var/tmp/${USER}_ssh_agentd_info >/dev/null

After editing the files run the following:

systemctl --user enable ssh-agent
systemctl --user start ssh-agent

Check the status or troubleshoot errors:

systemctl --user status ssh-agent

Useful options

If you wish to set environmental variables for your service, add the following settings:

[Service]
Environment=PLAYERNAME=JOHN
Environment=PLAYERSKILL=EASY

The variables are for example only. They are not supported by Minecraft.

If you want the service to work on behalf of a particular user, set these properties:

[Service]
User=john
Group=users

Steps after the configuration files are ready

Next, enable the service and start:

systemctl enable minecraft
systemctl start minecraft

You can monitor the output:

journalctl -f u minecraft

links

social