systemd-run: Ad-Hoc Transient Units Without Writing Unit Files

2026-06-02

Everyone reaches for nohup, tmux, or at when they want to background a job. Almost nobody reaches for the tool that systemd itself uses under the hood: systemd-run. It launches an arbitrary command as a transient service, scope, or timer — giving you journal logging, real cgroup-enforced resource caps, sandboxing, and calendar scheduling without ever writing a .service file.

The basic split: --scope runs the command inside your current terminal as the foreground process. --service (the default) forks a detached unit you talk to via journalctl/systemctl.

Capture stdout, stderr, and exit code in the journal, keyed by a unit name:

systemd-run --user --unit=nightly-ingest ./ingest.sh
journalctl --user -fu nightly-ingest.service
systemctl --user status nightly-ingest.service

Cap a runaway build at 4 GB and two cores — actual kernel enforcement, not ulimit wishful thinking:

systemd-run --user --scope \
    -p MemoryMax=4G -p MemorySwapMax=0 \
    -p CPUQuota=200% \
    cargo build --release

Block until done and return the exit code (great in CI scripts):

systemd-run --user --wait --pipe --collect \
    -p MemoryMax=2G ./flaky-converter input.bin

--pipe wires stdin/stdout through so it composes in pipelines. --collect garbage-collects the unit on exit so you don't accumulate failed-unit corpses.

Schedule a one-shot in 90 minutes, no at daemon needed:

systemd-run --user --on-active=90min \
    --unit=cache-purge /usr/local/bin/purge.sh

A recurring timer with calendar syntax that beats cron's:

systemd-run --user --on-calendar="Mon..Fri 09:30" \
    --unit=workday-report ./report.sh

Drop into a sandboxed shell — no network, private /tmp, read-only system, writable only where you say:

systemd-run --user --pty --same-dir \
    -p PrivateNetwork=yes -p PrivateTmp=yes \
    -p ProtectSystem=strict \
    -p ReadWritePaths=$PWD \
    bash

Inspect everything transient currently running:

systemctl --user list-units --type=service "run-*" "*.service"
systemd-cgls --user
systemd-cgtop

Why this beats the alternatives:

Gotchas worth knowing:

Once you internalize that "run a command" and "configure a systemd unit" are the same operation, you stop writing .service files for half the things you used to.

Key Takeaway: systemd-run turns any one-off command into a fully-featured transient systemd unit — cgroup limits, journal logs, sandboxing, and calendar timers — without ever editing a unit file.

All newsletters