linux / systemd

I run long-lived processes on Linux VMs as systemd services so they survive SSH logout and restart on crash or reboot. Read their output with linux / logs.

A service unit

A unit file describes how to start a process. This runs the farmer from cmd / cibot:

# /etc/systemd/system/cibot-farmer.service
[Unit]
Description=cibot farmer
After=network-online.target
Wants=network-online.target

[Service]
User=croaky
EnvironmentFile=/etc/cibot-farmer.env
ExecStart=/usr/local/bin/cibot farmer
Restart=always
RestartSec=2

[Install]
WantedBy=multi-user.target

Install and start it:

sudo cp cibot-farmer.service /etc/systemd/system/
sudo systemctl enable --now cibot-farmer

enable starts it on every boot and --now also starts it right away. Restart=always brings it back if it exits.

Template units

To run several copies of one process, use a template unit. The @ suffix and %i placeholder let a single file serve many instances:

# /etc/systemd/system/cibot-worker@.service
[Service]
User=croaky
EnvironmentFile=/etc/cibot.env
ExecStart=/usr/local/bin/cibot worker
Restart=always
sudo systemctl enable --now cibot-worker@{1..8}

That starts eight workers, cibot-worker@1 through @8, from one unit file.

Environment variables

systemd gives a process a minimal environment, so I keep config and secrets in an EnvironmentFile. The path /etc/cibot.env is my own choice; Debian and Ubuntu favor /etc/default/<name>, and Red Hat favors /etc/sysconfig/<name>.

# /etc/cibot.env
FARMER_URL=http://10.50.96.89:1994
BOX_TOKEN=...
PATH=/usr/local/go/bin:/usr/local/bin:/usr/bin:/bin

Two things worth knowing:

Everyday commands

sudo systemctl restart cibot-farmer
sudo systemctl stop cibot-farmer
systemctl is-active cibot-farmer
systemctl show cibot-farmer -p NRestarts --value

After editing a unit file, reload systemd's view before restarting:

sudo systemctl daemon-reload

← All articles