Service Manager · Unit Files · Journal · Boot
active or inactive — exit code 0 = activeenabled, disabled, masked, etc.graphical.target), stopping units not in itmulti-user.target.[Unit] Description=My Application Server # shown in systemctl status Documentation=https://example.com/docs # man: or https: URI After=network-online.target # ordering — start after network Wants=network-online.target # soft dependency (won't fail if missing) Requires=postgresql.service # hard dependency — fails if dep fails PartOf=myapp.target # stop/restart together with target [Service] Type=simple # simple|forking|oneshot|notify|idle User=myapp # run as this user Group=myapp WorkingDirectory=/opt/myapp EnvironmentFile=/etc/myapp/env # load KEY=VALUE pairs from file ExecStartPre=/opt/myapp/check-config.sh # run before main process ExecStart=/opt/myapp/bin/server --port 8080 ExecReload=/bin/kill -HUP $MAINPID # what systemctl reload does ExecStop=/bin/kill -TERM $MAINPID Restart=on-failure # no|always|on-failure|on-abnormal RestartSec=5s # wait before restarting TimeoutStartSec=30s TimeoutStopSec=30s StandardOutput=journal # stdout → journald StandardError=journal SyslogIdentifier=myapp # tag in journal (journalctl -t myapp) # Hardening NoNewPrivileges=yes ProtectSystem=strict ProtectHome=yes PrivateTmp=yes ReadWritePaths=/var/lib/myapp [Install] WantedBy=multi-user.target # systemctl enable creates link here
[Unit] Description=Daily backup for myapp [Timer] OnCalendar=*-*-* 02:30:00 # every day at 02:30 local time RandomizedDelaySec=5min # jitter — prevents thundering herd Persistent=true # catch up if the timer was missed Unit=myapp-backup.service # defaults to same-named .service [Install] WantedBy=timers.target
/etc/systemd/system/unit.d/override.conf — created by systemctl edit unit. Takes precedence over the vendor file.ExecStart=), set it empty first, then to the new value:ExecStart=
ExecStart=/new/cmd/lib/systemd/system/ — vendor units/etc/systemd/system/ — admin overrides~/.config/systemd/user/ — user unitssystemctl daemon-reload after adding or changing a unit file, then systemctl restart unit to apply.systemctl --user. Enable lingering with loginctl enable-linger user to keep them alive after logout.simple — main process is ExecStartforking — daemonizes via forkoneshot — runs to completionnotify — signals readiness via sd_notify0 emerg 1 alert 2 crit3 err 4 warning 5 notice6 info 7 debug/var/log/journal/ to make logs persist across reboots. Otherwise stored in /run/log/journal/ (volatile)./etc/systemd/journald.conf: SystemMaxUse=, MaxRetentionSec=, RateLimitBurst=.multi-user.target ≈ runlevel 3; graphical.target ≈ runlevel 5.systemctl are just D-Bus clients. Third-party apps can start/query units programmatically.Requires= — hard dep. Wants= — soft dep. After=/Before= — ordering only. These are orthogonal — you usually need both Wants + After..d/override.conf files. Survives package upgrades. Created safely with systemctl edit.systemd-run --unit=name cmd starts a one-off transient service. Useful for testing ExecStart lines or running tasks under resource limits.Type=notify and call sd_notify(READY=1) when fully started. systemd waits for this signal before marking the service active.ProtectSystem=strict, PrivateTmp=yes, NoNewPrivileges=yes apply kernel-level restrictions — no code changes required.WatchdogSec=30s and call sd_notify(WATCHDOG=1) from your app. systemd will restart the service if it stops sending pings.After= for network-dependent servicesWantedBy= this to enable a timergraphical.target or multi-user.target/etc/inittab, spawned getty processes, and executed shell scripts in /etc/rc.d/ or /etc/init.d/ in strict numeric order. Runlevels (0–6) defined which services were active. It worked, but its age showed badly by the 2000s.
bash script implementing start/stop/status/reload by hand. No consistency, no standard, constant reimplementation of the same boilerplate.S20foo, S80bar) encoded ordering but said nothing about why. A service that needed the network had to guess the right number..service format replaces hundreds of subtly different shell scripts. ExecStart= is just the binary to run.Requires=, Wants=, After=, Before= express what a service actually needs, and systemd computes the correct startup order.Restart=on-failure in a unit file is all it takes. systemd monitors the PID and restarts on crash with configurable backoff.network-online.target is a real synchronization point, not a guessed number.filesystem, net-device-up) and could emit their own events when ready. It was a genuine improvement, but lost the init wars to systemd by 2015.
start on / stop on event syntax was powerful but hard to reason about. Dependencies expressed as events were implicit; you had to know which events existed and when they fired.Requires=/After= concept. Ordering fell out of event sequencing, which was opaque and hard to audit..service files for systemd got a format that worked across all distros. Writing Upstart jobs was Ubuntu-specific work that few wanted to duplicate.systemctl list-dependencies nginx shows exactly what must start first and why, with no implicit event reasoning required..socket units hold open sockets across service restarts, enabling zero-downtime upgrades and lazy service start with no connections dropped.journald captures everything from every unit without per-service configuration. Upstart's logging story relied on each job redirecting its own output.supervise, which watches a process directory and restarts the process if it exits. It is still used today, particularly in high-security or minimal environments. Its design directly inspired runit, s6, and perp.
multilog writing to per-service directories. No unified query interface; searching across services requires grep across directories.run script in a specific directory layout. No standard format; packaging integration is poor.Requires= and After= ensure services start in the correct order with automatic retry if a dependency fails.journalctl -u nginx -f works the same way for every service without per-service log setup..service files. Enabling a service is systemctl enable foo — no directory trees to manage by hand.run files.log process writing to its own directory. Cross-service log querying requires custom tooling..socket units keep listening sockets alive across restarts, enabling zero-downtime service upgrades transparently.MemoryLimit=512M in a unit file is all it takes to cap a service's RAM usage..service file works on Fedora, Ubuntu, Debian, Arch, openSUSE, and RHEL. Upstream projects ship unit files; operators don't write them from scratch.need/use/before/after declarations in service scripts. It is the default on Gentoo and Alpine Linux, and is well-regarded for being understandable and hackable.
.service file. Unit files are validated, parsed, and version-controlled cleanly.Restart=on-failure in the unit file. No separate supervisor needed; the same daemon that starts a service also watches and restarts it.journalctl --since yesterday -p err finds errors across the whole system instantly..plist files to declare services, their environment, and restart behavior. systemd's unit files serve the same purpose in a more readable INI format.systemd-sysupdate for A/B OS updates ship. systemd becomes a platform for the full trusted boot chain, not just PID 1.