Skip to content

systemd Timers, Journald, cgroups, and Resource Control

Scope

This document covers four systemd areas that show up constantly in real operations:

  • timer units
  • journald
  • transient units and scopes
  • cgroup-based resource control

Reference anchors: - https://www.freedesktop.org/software/systemd/man/systemd.timer.html - https://www.freedesktop.org/software/systemd/man/systemd-journald.service.html - https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html - https://www.freedesktop.org/software/systemd/man/systemd.unit.html


1. Timers: The Cron Replacement That Actually Understands the System

A timer unit activates another unit, usually a service.

Why timers are often better than cron:

  • integrated with dependency graph
  • boot-aware
  • can be persistent
  • logs are tied to the activated service
  • calendar syntax is expressive
  • can use monotonic timers relative to boot or activation

Two timer families

Monotonic

Examples: - OnBootSec= - OnStartupSec= - OnUnitActiveSec= - OnUnitInactiveSec=

Good for: - "run 5 minutes after boot" - "run every 15 minutes after last success"

Calendar

Example: - OnCalendar=Mon..Fri 03:00

Good for wall-clock scheduling.

Persistent=true

This matters. If the machine was off during a scheduled run, the timer can catch up on next boot.

That alone makes timers better than a lot of crusty cron use.


Timer Pattern

A timer triggers a service. Do not jam logic into the timer itself.

Example:

# backup.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/do-backup
# backup.timer
[Timer]
OnCalendar=daily
Persistent=true

That separation gives you: - manual run capability - clean logging - testability - reusable policy


2. Journald: Structured Logging, Not Just a File Dump

systemd-journald collects logs from:

  • kernel
  • stdout/stderr of services
  • syslog-compatible sources
  • native journal API clients

The journal is indexed and metadata-rich.

Useful metadata includes: - boot ID - unit name - pid - uid - executable - priority - transport source

This is why journalctl -u sshd.service -b is so much nicer than spelunking random files.

Persistent vs volatile journals

Depends on configuration and whether persistent storage is enabled.

In practice: - some systems keep logs only under /run - others persist under /var/log/journal

You should know which mode your fleet uses before a bad day.

High-value commands

journalctl -b
journalctl -u nginx.service
journalctl -k
journalctl --since today
journalctl -p warning..alert

Why journald matters operationally

  • unit-scoped debugging
  • boot-scoped debugging
  • metadata-rich filtering
  • easier correlation than grep-over-flat-files
  • integration with service supervision

3. cgroups and Slices

Modern systemd uses cgroup v2 heavily.

Key concepts: - a service is usually a managed cgroup for a daemon/workload - a scope is a cgroup for externally created processes - a slice is a hierarchy partition used for grouping/resource policy

Service

Created and supervised by systemd via unit file or transient service.

Scope

Useful when processes were not originally spawned by systemd but you still want tracking/accounting. Example: - systemd-run --scope make -j16

Slice

A resource domain. You can place services under slices like: - system.slice - user.slice - custom slices

This lets you shape resource policy by class of workload.


4. Resource Control

This is where systemd stops being just a startup tool and becomes a policy engine.

Examples: - CPUWeight= - MemoryMax= - MemoryHigh= - IOWeight= - TasksMax=

These map into cgroup v2 controllers.

Why this matters

Without cgroup-level control: - one service can thrash memory - one process family can fork bomb - noisy neighbors can dominate CPU or IO

With resource control: - you can constrain damage - enforce fairness - make service classes explicit

Important nuance

MemoryHigh= is pressure/throttling territory. MemoryMax= is a hard ceiling.

Know the difference. One is "back off." The other is "you hit the wall."


5. Transient Units

systemd-run lets you create units dynamically.

Examples:

systemd-run --unit=adhoc-backup --on-active=30s /usr/local/bin/backup-now
systemd-run --scope -p CPUWeight=200 make -j8

This is very useful in operations: - ad hoc resource-constrained jobs - reproducible one-off tasks - cleaner than "nohup and vibes"


6. Using Timers + Journald + cgroups Together

This is the real-world pattern.

Example: - nightly backup runs via timer - backup service logs to journald - backup service limited by IOWeight= and CPUWeight= - failures visible with journalctl -u backup.service

That is much saner than: - cron - unbounded resource use - logs redirected to mystery file - no state integration


Common Mistakes

Timer without service

Timers activate units, they do not replace them.

Using shell redirection instead of journald integration

You lose a lot of useful metadata.

No persistence policy for logs

Then during incident review you discover the evidence was living in RAM.

No resource limits for risky services

Then a bad deploy eats the box.

Confusing scope and service

A service is managed lifecycle. A scope is tracked externally-created processes.


Operational Commands

systemctl list-timers
systemctl status backup.timer
systemctl status backup.service
journalctl -u backup.service
journalctl -b -1
journalctl --disk-usage
systemctl status myservice.service
systemctl show myservice.service | grep -E 'Memory|CPU|Tasks'
systemd-cgls
systemd-cgtop

Interview-Level Things to Explain

You should be able to explain:

  • why timers are better than cron in many Linux fleets
  • what Persistent=true does
  • how journald differs from flat log files
  • difference between service, scope, and slice
  • how systemd enforces CPU/memory/IO policies through cgroups
  • why resource isolation matters on shared hosts

Fast Mental Model

Timers schedule work.
Journald explains what happened.
cgroups bound the damage.
systemd ties all three together.

Wiki Navigation

Prerequisites