VPS Tutorials
How to Read VPS Logs (2026): Using journalctl, systemctl, Nginx, and Application Logs to Diagnose Problems
When your VPS has problems, don't just restart services. This article follows the order of systemctl, journalctl, Nginx access/error logs, Docker logs, and application logs to explain clearly how to pinpoint port, permission, configuration, memory, and startup failure issues from logs.

Many VPS problems are actually already written clearly in the logs—it's just that nobody looks.
I once saw a friend whose Node service kept failing to start. He repeatedly ran:
systemctl restart app
After restarting a dozen times it still didn't work. Finally he took a look at the logs, and they clearly said EADDRINUSE: address already in use—the port was occupied by an old process. The problem wasn't an unstable server, nor was it code mysticism; it was simply not reading the logs.
So this article doesn't cover complex monitoring. It covers only the most practical thing: when your VPS has problems, where to look at logs first, how to read them, and which direction to investigate when you see certain keywords.
When a service has problems, the first command is usually:
systemctl status 服务名
For example:
systemctl status nginx
systemctl status docker
systemctl status mysql
systemctl status app
Focus on these lines:
- Whether
Active:is running, failed, or activating - Whether
Main PID:has a process - Whether the last few log lines have errors
- What the exit code after
code=exitedis - Whether there are hints like
permission denied,address already in use,cannot bind
systemctl status is good for quickly judging the current service status, but it only shows a small snippet of logs. To see the full logs, use journalctl.
If the service is managed by systemd, the most commonly used command is:
journalctl -u 服务名 -n 100 --no-pager
For example:
journalctl -u nginx -n 100 --no-pager
journalctl -u docker -n 100 --no-pager
journalctl -u app -n 100 --no-pager
To watch logs in real time:
journalctl -u 服务名 -f
To see logs after a certain time:
journalctl -u 服务名 --since "1 hour ago"
journalctl -u 服务名 --since "2026-05-13 10:00:00"
If a service just failed to restart, I usually look at it like this:
systemctl restart app
journalctl -u app -n 100 --no-pager
Don't just look at the last line. Many real causes are a dozen or so lines from the bottom—for example, failure to read the configuration file, missing environment variables, or port occupation.
Some problems aren't problems with a single service, but problems at the boot, disk, memory, network, or kernel level.
To view logs since this boot:
journalctl -b -n 200 --no-pager
To view logs from the previous boot:
journalctl -b -1 -n 200 --no-pager
If the VPS reboots for no reason or services suddenly die, you can check:
last reboot
journalctl -b -1 -p warning --no-pager
Common keywords:
Out of memory: not enough memory, killed by OOMKilled process: a process was killed by the systemsegfault: program crashedI/O error: disk or filesystem problemNo space left on device: disk is fullpermission denied: permission problem
These are far more useful than "the server feels unstable."
The two most commonly checked Nginx logs:
/var/log/nginx/access.log
/var/log/nginx/error.log
To watch errors in real time:
tail -f /var/log/nginx/error.log
To see recent access:
tail -n 100 /var/log/nginx/access.log
If the browser gets a 502, check the error log first. Common causes:
- Wrong upstream port
- Backend application not started
- Nginx has no permission to access the socket
- PHP-FPM is down
- Reverse proxy connection timeout
If you get a 404, check the access log and the server block. It could be:
- The domain went to the wrong server_name
- The root path is written incorrectly
- The rewrite rules are wrong
- The static file doesn't exist
If it's a 403, it's commonly a permission or directory index problem.
After changing the Nginx configuration, run this first:
nginx -t
systemctl reload nginx
Don't restart directly. nginx -t can tell you in advance whether the configuration has syntax errors.
When a Docker container dies, many people only look at:
docker ps
But the real cause is usually in the logs:
docker logs 容器名 --tail 100
docker logs -f 容器名
If it's docker compose:
docker compose ps
docker compose logs --tail 100 服务名
docker compose logs -f 服务名
Common keywords:
permission denied: wrong permissions on the mounted directoryconnection refused: dependent service not up or wrong addressno such file or directory: wrong configuration file pathaddress already in use: port conflictexit code 137: commonly killed due to insufficient memory
When a container keeps restarting, don't just change restart: always. It only makes the container keep restarting; it can't solve the root cause.
Different applications have different log locations.
Common locations:
/var/log/应用名/
/opt/应用名/logs/
/home/用户名/app/logs/
pm2 logs
If it's Node + PM2:
pm2 status
pm2 logs --lines 100
If it's Python / Gunicorn:
journalctl -u gunicorn -n 100 --no-pager
If it's PHP-FPM:
journalctl -u php8.2-fpm -n 100 --no-pager
When you can't find the logs, look at the service file first:
systemctl cat 服务名
You can usually see the startup command, working directory, and environment variable file in it. Many "the program won't start" causes are actually a wrong working directory, environment variables not loaded, or a wrong configuration file path.
Here's a quick reference table:
| Log keyword | Common direction |
|---|---|
address already in use | Port already in use |
permission denied | File permissions, directory permissions, port permissions |
connection refused | Dependent service not started, port unreachable |
no such file or directory | Wrong path, file doesn't exist |
No space left on device | Disk full, inodes full |
Out of memory / Killed process | Insufficient memory, OOM kill |
bad gateway / upstream | Nginx can't reach the backend |
certificate / SSL | Certificate, domain, HTTPS configuration problems |
authentication failed | Password, permission, database user problems |
timeout | Slow network, stuck dependencies, firewall blocking |
After seeing a keyword, don't rush to copy the whole error and search for it. First judge based on the scenario: is this the startup phase, the access phase, the database connection phase, or the reverse proxy phase?
If you're going to open a ticket or ask someone for help, the logs should be pasted just right.
Suggested to provide:
systemctl status 服务名
journalctl -u 服务名 -n 80 --no-pager
nginx -t
ss -lntp
If it's a website problem, also add:
tail -n 80 /var/log/nginx/error.log
tail -n 50 /var/log/nginx/access.log
Don't paste thousands of lines of logs directly. Others can't finish reading them, and it's easy to miss the key points.
More importantly, redact before pasting logs:
- Server IP
- Database password
- API Key
- Token
- Cookie
- User email
- Admin panel path
Logs often contain sensitive information, especially application error stacks and request headers. Be sure to check before posting publicly to forums or group chats.
If a service on a VPS has problems, I usually follow this order:
systemctl status 服务名journalctl -u 服务名 -n 100 --no-pagerss -lntpto check portsdf -hto check diskfree -mto check memory- Nginx error log / access log
- The application's own logs
- Docker / PM2 / PHP-FPM logs
- What configuration was changed most recently
- Then decide whether to restart, roll back, or change the configuration
This is much more reliable than "let's try restarting." Restarting can sometimes temporarily recover things, but it also wipes out the scene. Especially for intermittent problems, logs are the evidence.
When you run into a problem, first ask yourself:
- Is the service status running or failed
- Are there obvious errors in the last 100 lines of
journalctl -u - Are there port occupation, permission, path, disk, or memory errors
- Does the Nginx error log have upstream / 502 / 403 / 404 information
- Do Docker or PM2 have separate logs
- Have the configuration, certificates, environment variables, or dependency versions been changed recently
- Have the logs been redacted before sending them to others
The worst thing in VPS troubleshooting is relying on feelings. Logs may not directly tell you the answer, but they will tell you where to look next. Look at the logs first, then make changes—you'll avoid many detours.