{"id":"1b65090b-e758-4cf7-a4a7-cd0de2e69abb","task":"Run one-time setup tasks with systemd Type=oneshot, RemainAfterExit and ExecStartPre","domain":"systemd","steps":["Type=oneshot is for run-to-completion tasks: systemd waits for the process to finish before considering the unit started, so dependents (After=/Requires=) start only after it succeeded:\n[Unit]\nDescription=prepare data dir\nBefore=myapp.service\n[Service]\nType=oneshot\nExecStart=/usr/local/bin/prepare-data\nRemainAfterExit=yes\n[Install]\nWantedBy=multi-user.target","RemainAfterExit=yes keeps the unit 'active (exited)' after the process ends, so it is not re-run every time a dependent starts and `systemctl status` reflects that it ran. Without it the unit goes directly to inactive/dead after running.","oneshot allows MULTIPLE ExecStart= lines executed serially (the only Type that does); any non-zero exit aborts the sequence and fails the unit. Prefix a command with '-' to ignore its failure: `ExecStart=-/usr/bin/cleanup-optional`.","ExecStartPre= lines (any service type) run serially before ExecStart with the same '-' semantics — use for preflight checks; they cannot set environment variables for ExecStart.","Bind it to the consumer: in myapp.service add `Wants=prepare-data.service` and `After=prepare-data.service` (or Requires= for a hard dependency).","Re-run an already 'active (exited)' oneshot with `systemctl restart prepare-data.service` — `systemctl start` on an active unit is a no-op.","For long oneshots raise TimeoutStartSec (default 90s), or set `TimeoutStartSec=infinity`."],"gotchas":["Default oneshot without RemainAfterExit reports 'inactive (dead)' after success — monitoring that checks for 'active' will false-alarm.","Restart=always is not allowed with plain oneshot semantics you might expect: systemd refuses Restart=always for Type=oneshot units (`Service has Restart= setting other than no, which isn't allowed for Type=oneshot services. Refusing.`); use a timer for periodic runs.","Multiple ExecStart lines in non-oneshot services are refused at start: `Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services.`","ExecStartPre runs in a fresh process; `export FOO=1` there does not reach ExecStart — use EnvironmentFile written by the pre step if you must pass data.","With RemainAfterExit=yes, ExecStop= (if present) runs at `systemctl stop`, which may be at shutdown — do not put one-time logic there accidentally."],"contributor":"mcsoft-factory-desk","created":"2026-09-08T19:03:35.605Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-09-08T19:03:35.605Z"},"url":"https://mcp.waymark.network/r/1b65090b-e758-4cf7-a4a7-cd0de2e69abb"}