Skip to content

systemctl status Explainer: Paste It, Get the Cause

Quick Answer

The systemctl status Explainer reads the output of systemctl status, journalctl -u or the "Job for X.service failed" message and tells you why the service is not running. It decodes the Main PID line, so status=203/EXEC, 200/CHDIR and 217/USER are named as setup steps that failed before your program ran, while status=1/FAILURE is the program's own exit and comes with the program's last journal lines. It reads the journal line that names the cause: Unable to locate executable for a missing or relative ExecStart= path, Exec format error for a script with no #! line, No such file or directory for a missing or CRLF interpreter, and Start request repeated too quickly for a crash loop that hit the start limit. It also catches OOM kills, start timeouts, masked units, units that cannot be found and edits that need daemon-reload. Each cause comes with the next command, with --user filled in for user units. Parsing runs in your browser and redaction is on by default.

How to use the systemctl status Explainer: Paste It, Get the Cause

  1. 1Run `systemctl status NAME.service --no-pager -l` (add `--user` for a user unit) and paste all of it, journal lines included.
  2. 2Read the summary: the most likely cause and the one command to run next.
  3. 3Work down the cards: each quotes the line it is based on and gives a copy-paste command.
  4. 4If the status block alone is not enough, paste `journalctl -u NAME -n 50 --no-pager` under it.

Frequently Asked Questions

faq — tool

What does status=203/EXEC mean in systemd?

203/EXEC means systemd could not execute the program in ExecStart=, so your program never ran a single line. On systemd 261 the journal line before it names one of five causes: Unable to locate executable with No such file or directory (a wrong or relative path), Permission denied (no execute bit, or a noexec mount), Exec format error (a script with no #! line), or Failed to execute with No such file or directory on a file that exists (its #! interpreter is missing or the file has CRLF line endings).

faq — tool

Why does systemctl start succeed when the service failed?

For Type=simple, the default, systemctl start returns as soon as systemd has forked the process, before your program runs. A service that dies immediately, even with 203/EXEC, still gives exit 0 from systemctl start; we measured exactly that on systemd 261. Only Type=oneshot, forking and notify units wait and print "Job for X.service failed". Run systemctl is-active NAME a second later, or systemctl status, to see the real state.

faq — tool

How do I fix start request repeated too quickly?

Find out why each start failed first: journalctl -u NAME -n 50 shows the exit before the limit was hit. The limit itself is a symptom: by default systemd allows 5 starts in 10 seconds, then marks the unit failed with result start-limit-hit. Once the cause is fixed, run systemctl reset-failed NAME and start it again. To space retries out, set RestartSec= in [Service]; StartLimitBurst= and StartLimitIntervalSec= go in [Unit].

faq — tool

What is the difference between code=exited and code=killed in systemctl status?

code=exited, status=N means the process ended by itself with exit code N; codes 200 and up are set by systemd when a setup step failed before the program started. code=killed, signal=X means a signal ended it: KILL from kill -9, the OOM killer or a stop timeout, TERM from systemctl stop or a start timeout. code=dumped means it crashed and wrote a core dump, which coredumpctl can show.

faq — tool

Does this tool send my systemctl output anywhere?

No. The text is parsed in your browser and never uploaded. Redaction is on by default: the journal host name, the user name in /home paths and any IP address other than loopback are replaced before they are shown or put into a share link. The share link carries the redacted text in the URL fragment after the # sign, which browsers do not send to the server.

PAID RESOURCE — $9

The Production Bash Toolkit

An operational script system + a 30-function shared library + a 52-page field guide. The production layer the free snippets don't cover.

Get the Toolkit →
curl -O bashlib-starter.sh

Get the bashlib starter

Ten functions I source into every script on my own boxes — strict-mode setup, an ERR trap that names the failing line, lock and timeout wrappers, and cleanup that runs on every exit path. One email, no sequence.

Related Snippets