Skip to content

Running with systemd

Teuk edited this page Jul 3, 2026 · 2 revisions

Running Mediabot with systemd

This page documents the recommended runtime model for Mediabot v3 using systemd.

The old root-level helper scripts (start, stop, daemon) and the old cron watchdog approach are now considered legacy helpers. They may still exist under tools/legacy/ for reference, but systemd is the preferred supervisor for production and long-running instances.


Why systemd?

systemd is preferred because it provides:

  • automatic restart on failure;
  • clean start/stop/restart commands;
  • restart-loop protection;
  • journalctl logs;
  • better multi-instance management;
  • no dependency on fragile PID-file polling or cron watchdog loops;
  • atomic single-instance protection through the configured PID-file lock.

Mediabot should run in the foreground under systemd. Do not use --daemon in the systemd unit.


Instance model

A Mediabot instance is defined by:

- its project directory
- its configuration file
- its systemd instance name

The configuration file may stay at the root of each instance directory.

Common single-instance layout:

/home/mediabot/mediabot_v3
/home/mediabot/mediabot_v3/mediabot.conf

Multi-instance example:

/home/mediabot/mediabot_v3  -> dev instance,      mediabot.conf
/home/mediabot/mediabot3    -> Undernet instance, mbundernet.conf

Corresponding systemd units:

mediabot@dev.service
mediabot@undernet.service

Corresponding environment files:

/etc/default/mediabot-dev
/etc/default/mediabot-undernet

Template unit

Install the template as:

/etc/systemd/system/mediabot@.service

Example:

[Unit]
Description=Mediabot v3 IRC bot instance (%i)
After=network-online.target
Wants=network-online.target

StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Type=simple
User=mediabot
Group=mediabot

EnvironmentFile=/etc/default/mediabot-%i

WorkingDirectory=/
SyslogIdentifier=mediabot-%i

ExecStart=/bin/bash -lc 'cd "$BOT_DIR" && exec /usr/bin/stdbuf -oL -eL /usr/bin/perl "$BOT_BIN" --conf="$BOT_CONF"'

Restart=on-failure
RestartSec=10s

TimeoutStopSec=30
KillSignal=SIGTERM

StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Reload systemd after installing or changing the unit:

systemctl daemon-reload

Environment files

Each instance has a matching environment file:

/etc/default/mediabot-<instance>

Single/default instance example

/etc/default/mediabot-dev
BOT_DIR=/home/mediabot/mediabot_v3
BOT_BIN=/home/mediabot/mediabot_v3/mediabot.pl
BOT_CONF=/home/mediabot/mediabot_v3/mediabot.conf

Undernet-style separate directory example

/etc/default/mediabot-undernet
BOT_DIR=/home/mediabot/mediabot3
BOT_BIN=/home/mediabot/mediabot3/mediabot.pl
BOT_CONF=/home/mediabot/mediabot3/mbundernet.conf

The instance name in the unit must match the suffix of the environment file:

systemctl start mediabot@dev

loads:

/etc/default/mediabot-dev

Basic commands

Start:

systemctl start mediabot@dev

Stop:

systemctl stop mediabot@dev

Restart:

systemctl restart mediabot@dev

Status:

systemctl status mediabot@dev --no-pager

Logs:

journalctl -u mediabot@dev -f

Enable at boot:

systemctl enable mediabot@dev

Disable at boot:

systemctl disable mediabot@dev

Temporary pause during maintenance

To stop an instance and restart it automatically after 10 minutes:

systemctl stop mediabot@dev

systemd-run \
  --unit=mediabot-resume-dev \
  --on-active=10m \
  /bin/systemctl start mediabot@dev

List pending timers:

systemctl list-timers | grep mediabot

This is useful when you want to disable automatic relaunch during a short maintenance window.


Development helper: mbctl

The repository may provide a convenience wrapper:

tools/dev/mbctl

Examples:

tools/dev/mbctl list
tools/dev/mbctl dev status
tools/dev/mbctl dev restart
tools/dev/mbctl dev logs
tools/dev/mbctl undernet status
tools/dev/mbctl undernet pause 10m

mbctl is only a small wrapper around systemctl, journalctl, and systemd-run.

It does not replace systemd. It makes day-to-day development faster.


Before starting with systemd

Before starting an instance with systemd, check that it is not already running manually:

ps -fu mediabot | grep -E 'mediabot\.pl|perl' | grep -v grep

You should not run the same instance both manually and through systemd.

Current builds keep an exclusive lock on MAIN_PID_FILE for the complete process lifetime. A second process using the same config/PID path is refused before it connects to IRC. The PID file is removed during a clean SIGINT or SIGTERM shutdown.

Do not delete a PID file while its owner is alive. If a stale file contains a dead PID and no lock is held, the next legitimate process replaces it.

If an old root-level script was used, stop that old process first.


Legacy scripts

Old helper scripts may be kept under:

tools/legacy/

Typical legacy files:

start.legacy
stop.legacy
daemon.legacy
check_alive_cron_script.sh.legacy

They are kept for reference only. systemd is the recommended runtime supervisor.


ZNC / bouncer usage

systemd does not need to know whether Mediabot connects directly to an IRC server or through a bouncer such as ZNC.

Configure the IRC server, port, SSL, credentials, and bouncer details in the Mediabot configuration file.

The same systemd unit model works for:

- direct IRC server connections
- ZNC-backed instances
- test networks
- production networks

Validation checklist

After creating or modifying a systemd instance:

systemctl daemon-reload
systemctl start mediabot@dev
systemctl status mediabot@dev --no-pager
journalctl -u mediabot@dev -n 80 --no-pager

Then verify from IRC:

<prefix>version
<prefix>uptime
<prefix>help
<prefix>commands
<prefix>status
<prefix>status full
<prefix>whoami

version must answer locally, uptime and status must agree on process age, and long help output must arrive gradually without Excess Flood.

And from Partyline if enabled:

.stat
.console 3
.floodstatus
.netsplit

See also

Clone this wiki locally