Site icon BitBook

Use journalctl to Debug a Failed systemd Service

When a Linux service fails under systemd, the fastest first move is
usually not digging through random files in /var/log. Ask
systemd what happened, then use journalctl to pull the logs
for that exact unit.

Start with the service status:

sudo systemctl status nginx --no-pager

Replace nginx with your service name. The useful parts
are usually the Active: line and the last few log lines
near the bottom.

Example failure:

Active: failed (Result: exit-code) since Thu 2026-05-21 09:12:31 CDT; 22s ago
Process: 14822 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)
nginx[14822]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

That already tells us the service is not broken in some abstract way.
Something else is using port 80.

Show Logs for One Service

Use -u to filter logs to one systemd unit:

sudo journalctl -u nginx --no-pager

For recent failures, show the newest entries first:

sudo journalctl -u nginx -r --no-pager

Or limit it to the last 100 lines:

sudo journalctl -u nginx -n 100 --no-pager

--no-pager keeps the output from opening in
less, which is nicer when you are copying results or
running commands over SSH.

Show Logs Since the Last
Boot

If the machine was recently restarted, this keeps old noise out of
the way:

sudo journalctl -u nginx -b --no-pager

You can combine it with -n:

sudo journalctl -u nginx -b -n 200 --no-pager

This is usually the best command when a service fails after
reboot.

Follow Logs While Restarting

In one terminal, follow the service logs:

sudo journalctl -u nginx -f

In another terminal, restart the service:

sudo systemctl restart nginx

Now the error shows up live. This is useful for config problems where
systemctl status only shows the last few lines.

Filter by Time

If you know the approximate time the service broke, filter the
journal:

sudo journalctl -u nginx --since "2026-05-21 09:00" --until "2026-05-21 09:30" --no-pager

Human-friendly times also work:

sudo journalctl -u nginx --since "30 minutes ago" --no-pager

Check the Exact Unit Name

If you are not sure what the service is called:

systemctl list-units --type=service | grep -i nginx

For installed services that are not currently loaded:

systemctl list-unit-files --type=service | grep -i nginx

Use the full unit name from that output, like
nginx.service, with journalctl -u.

Common Failure Patterns

Port already in use:

sudo ss -ltnp | grep ':80'

Bad config:

sudo nginx -t

Permission problem:

sudo journalctl -u nginx -b --no-pager | grep -i 'permission\|denied'

Missing environment variable:

sudo systemctl cat nginx

The systemctl cat command shows the unit file and any
override files. That helps when the service works manually but fails
under systemd because it has a different environment.

Verify the Fix

After changing config or freeing a port, restart the service and
confirm it is active:

sudo systemctl restart nginx
sudo systemctl is-active nginx

Expected output:

active

Then check that no new errors were logged:

sudo journalctl -u nginx -b -n 50 --no-pager

For most systemd service problems, these three commands are enough to
get from “it failed” to a useful error:

sudo systemctl status SERVICE --no-pager
sudo journalctl -u SERVICE -b -n 200 --no-pager
sudo journalctl -u SERVICE -f

Replace SERVICE with the real unit name.

Safety note: journalctl and
systemctl status are read-only.
systemctl restart is not. Restarting a production service
can briefly interrupt traffic, so check what service you are touching
before running it.

Exit mobile version