How to Read Linux Logs with journalctl and tail
Learn the fastest beginner-friendly way to inspect service logs, follow live output, and turn vague server problems into evidence you can act on.
How to read systemd service logs with journalctl, inspect plain log files with tail, and narrow results by time, unit, and priority.
VPS troubleshooting, service crashes, Docker host issues, Nginx errors, and learning what actually happened before you start changing things.
Logs can contain sensitive paths, usernames, tokens, or request data. Read carefully and share selectively.
Before you begin
- A Linux machine that uses systemd, which includes most modern Ubuntu and Debian VPS setups.
- SSH access and permission to run
sudowhen needed. - The name of the service, container host, or application you are trying to inspect.
When something breaks on Linux, logs are often the shortest path to the truth. Without them, troubleshooting turns into guessing. With them, you can see whether a service failed to start, a port was already in use, a certificate path was wrong, a database connection was refused, or a reverse proxy route pointed nowhere.
Why beginners should learn this early
Many new operators react to errors by reinstalling, rebooting, or editing several configs at once. That usually makes the situation harder to understand. Reading logs first lets you debug from evidence. It saves time, reduces panic, and often points directly at the one broken assumption that actually matters.
Step 1: Use journalctl for systemd services
If your app is managed by systemd, journalctl is usually your first stop. Start with the service name:
sudo systemctl status myapp
sudo journalctl -u myapp -n 50 --no-pagerUseful patterns:
-u myappfilters to one service unit.-n 50shows the last 50 lines.--no-pagerprints directly to the terminal.-ffollows logs live.
Follow logs while you restart a service:
sudo journalctl -u myapp -fIn another SSH session, restart it:
sudo systemctl restart myappThis is one of the fastest ways to catch startup errors in real time.
You can also search by time:
sudo journalctl -u myapp --since "10 minutes ago"
sudo journalctl -u myapp --since today
sudo journalctl -u myapp --since "2026-04-22 15:00:00"And filter by priority for more urgent messages:
sudo journalctl -p err -b
sudo journalctl -u myapp -p warning --since today-b means current boot. That is helpful when troubleshooting problems introduced after a reboot.
Step 2: Use tail for plain log files
Not every useful log is in the journal. Nginx, app frameworks, and custom scripts often write to files in places like /var/log/.
Read the last lines of a file:
sudo tail -n 50 /var/log/nginx/error.log
sudo tail -n 50 /var/log/nginx/access.logFollow a file live:
sudo tail -f /var/log/nginx/error.logCommon places to look:
/var/log/nginx/error.logfor reverse proxy failures/var/log/nginx/access.logfor request patterns and status codes- Application logs under the app directory or a logging path the app defines
- Docker container logs through
docker logsif the app logs to stdout rather than a file
If a service is containerized, pair host-level and container-level inspection:
docker ps
docker logs --tail=50 my-container
docker logs -f my-containerStep 3: Use a real troubleshooting workflow
Here is a simple pattern you can reuse when a site or app goes down:
- Confirm the failing symptom from the outside, for example with
curl -I https://example.com. - Check service status with
systemctl status. - Read recent service logs with
journalctl -u SERVICE -n 50 --no-pager. - If a reverse proxy is involved, inspect Nginx or Caddy logs.
- If the app runs in Docker, inspect container logs too.
- Make one change at a time, then re-check logs.
Example: a Node app behind Nginx returns 502. You might run:
curl -I https://example.com
sudo systemctl status myapp
sudo journalctl -u myapp -n 100 --no-pager
sudo tail -n 50 /var/log/nginx/error.logThe logs may reveal that the app never started, is listening on the wrong port, or crashed because an environment variable is missing. That is much more useful than changing random proxy settings and hoping.
Expected outcomes and what good looks like
After working through this guide, you should be able to:
- Read recent logs from a systemd service quickly.
- Follow logs live while starting or restarting a service.
- Open and follow file-based logs with
tail. - Use time filters to focus on the period when a failure happened.
- Explain the difference between service logs, reverse proxy logs, and container logs.
The real sign of progress is not memorizing flags. It is becoming less likely to guess and more likely to gather evidence first.
Troubleshooting and common mistakes
journalctl says you do not have permission.
Use sudo, or ensure your user has the right privileges on the system.
The log output is overwhelming.
Start smaller. Use -n 50, filter by unit, and add a time range like --since "10 minutes ago".
The service looks active, but the app is still broken.
A running process does not guarantee healthy behavior. Check proxy logs, app logs, container logs, and actual request results too.
I cannot find the log file.
Read the app or web server config to see where it writes logs, or check whether it logs only to stdout and is meant to be viewed through journalctl or docker logs.
What to do next
Once you can read logs confidently, the next useful skill is automating recurring server chores without cron sprawl. Continue with How to Schedule Backups and Maintenance with systemd Timers.
