systemctl Restart Service Not Working: Fix Guide

Fix systemctl restart not working — diagnose failed units, read journal logs, handle dependency failures, and resolve the most common systemd service restart failures.

April 22, 2026·6 min read·Damon

systemctl restart myapp returns no error but the service stays dead, or keeps crashing, or the command itself fails. Here's the diagnostic path to find and fix it.


TL;DR

# Step 1: what's the actual state?
systemctl status myapp

# Step 2: what did it log?
journalctl -u myapp -n 50 --no-pager

# Step 3: why did it fail?
journalctl -u myapp --since "5 minutes ago" -p err

# Step 4: check dependencies
systemctl list-dependencies myapp

Step 1: Read the Status Output Carefully

systemctl status myapp

Example output for a failed service:

● myapp.service - My Application
   Loaded: loaded (/etc/systemd/system/myapp.service; enabled)
   Active: failed (Result: exit-code) since Mon 2026-04-20 14:22:03 UTC
  Process: 4521 ExecStart=/opt/app/start.sh (code=exited, status=1/FAILURE)
 Main PID: 4521 (code=exited, status=1/FAILURE)

Apr 20 14:22:03 server01 systemd[1]: myapp.service: Main process exited, code=exited, status=1/FAILURE
Apr 20 14:22:03 server01 systemd[1]: myapp.service: Failed with result 'exit-code'.
Apr 20 14:22:03 server01 systemd[1]: Failed to start My Application.

Key fields:

Field What it means
Active: failed (Result: exit-code) Process exited with non-zero status
Active: failed (Result: signal) Process was killed by a signal (OOM, SIGKILL)
Active: activating (auto-restart) Systemd is restarting it in a loop
status=1/FAILURE Exit code from the process
code=killed, signal=KILL OOM killer or manual kill -9

Step 2: Read the Full Journal

Status output is truncated. Get the full story:

# Last 50 lines
journalctl -u myapp -n 50 --no-pager

# Since last restart attempt
journalctl -u myapp --since "5 minutes ago" --no-pager

# Errors only
journalctl -u myapp -p err --since "today"

# From a previous boot (if service crashed and caused a reboot)
journalctl -b -1 -u myapp | tail -50

Common Failure Patterns and Fixes

Pattern 1: Service starts then immediately exits

Active: failed (Result: exit-code)

The process started but exited with an error. The exit code tells you where to look:

journalctl -u myapp -n 30 --no-pager
# Look for application-level error messages before the systemd "Failed" line

Common causes:

  • Missing config file
  • Wrong permissions on files the app needs
  • Port already in use
  • Missing environment variable
# Test manually with same user as the service
runuser -u appuser -- /opt/app/start.sh
# This shows the real error without systemd interference

Pattern 2: Start limit hit — systemd stops trying

Active: failed (Result: start-limit-hit)

The service crashed and restarted too many times. Systemd backs off.

# Reset the failure counter to allow restarting
systemctl reset-failed myapp
systemctl start myapp

To prevent this in production, tune the restart limits in the unit file:

[Service]
Restart=on-failure
RestartSec=5s
StartLimitBurst=5          # allow 5 restarts
StartLimitIntervalSec=60s  # within 60 seconds

Pattern 3: Signal kill — OOM or external kill

Active: failed (Result: signal)
code=killed, signal=KILL

Check if OOM killer was responsible:

journalctl -k --since "1 hour ago" | grep -i "oom\|killed"
dmesg | grep -i "oom\|killed process" | tail -10

If OOM: the service doesn't have enough memory. Increase memory limits or reduce the service's memory usage.

# Unit file — set memory limit to prevent OOM kill
[Service]
MemoryMax=2G
MemoryHigh=1.5G

Pattern 4: Dependency failed

Active: inactive (dead)
Condition: start condition failed

A required service or condition wasn't met:

# Check what dependencies are needed
systemctl list-dependencies myapp

# Check which dependencies are failing
systemctl status $(systemctl list-dependencies myapp --plain | head -5)

Example: service requires a network mount that isn't ready:

[Unit]
After=network-online.target mnt-data.mount
Requires=mnt-data.mount

Pattern 5: Unit file syntax error

Failed to load configuration: Invalid argument
# Validate unit file syntax
systemd-analyze verify /etc/systemd/system/myapp.service

# After editing unit file, always reload daemon
systemctl daemon-reload
systemctl restart myapp

Forgetting daemon-reload after editing a unit file is the most common mistake. systemd caches unit files — changes don't take effect until you reload.

Pattern 6: Permission or file not found

code=exited, status=203/EXEC

Status 203 means the ExecStart binary couldn't be executed:

# Check the path in the unit file
systemctl cat myapp | grep ExecStart

# Verify it exists and is executable
ls -la /opt/app/start.sh
# Check it's not a script with wrong line endings (Windows CRLF)
file /opt/app/start.sh

Full Diagnostic Workflow

# 1. Get current state
systemctl status myapp

# 2. Get logs with context
journalctl -u myapp -n 100 --no-pager

# 3. Test the command directly
systemctl cat myapp | grep ExecStart
# Run that command manually as the service user

# 4. Check for start-limit issues
systemctl is-failed myapp
systemctl reset-failed myapp

# 5. After any unit file change
systemctl daemon-reload

# 6. Restart and watch
systemctl restart myapp && journalctl -fu myapp

Common Mistakes

Mistake 1: Not running daemon-reload after editing the unit file Changes to /etc/systemd/system/myapp.service have zero effect until you reload.

systemctl daemon-reload    # always do this after editing unit files

Mistake 2: Looking at truncated status output systemctl status shows ~10 lines. The real error is usually in journalctl.

Mistake 3: systemctl restart on a failed service without resetting limits If it hit StartLimitBurst, restart will be silently ignored. Always check for start-limit-hit.

Mistake 4: Testing as root when service runs as another user A script might work as root but fail for appuser due to file permissions.

# Test as the actual service user
runuser -u appuser -- /opt/app/start.sh

Pro Tips

# Watch service status live while troubleshooting
journalctl -fu myapp

# Check all failed units at once
systemctl --failed

# See the full unit file including overrides
systemctl cat myapp

# Override specific settings without editing the unit file
systemctl edit myapp
# Creates /etc/systemd/system/myapp.service.d/override.conf

# Check what the service is actually doing right now
systemctl status myapp --full

Conclusion

When systemctl restart doesn't work: check status for the failure reason, get the full journal log, run the command manually as the service user, and remember daemon-reload after any unit file change. start-limit-hit is the silent blocker that catches most people — systemctl reset-failed clears it.


Related: Linux Log Analysis: Debug Issues Like a Senior Engineer — journalctl deep dive for log investigation. Linux Process States Explained — understanding what happens to a process after systemd sends a signal.