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:
- The default
PATHis minimal, so set it explicitly when the process shells out to tools likego,git, orpsql. - The file holds secrets, so restrict it with
sudo chown root:root /etc/cibot.env && sudo chmod 600 /etc/cibot.env.
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