Logs tell you exactly what’s happening on your GoZen VPS. When a site goes down, a service crashes, or an attacker probes your ports, the answer is in the logs. This guide shows you where to look, what to look for, and how to work with logs efficiently.

Where Logs Live

Log FileWhat It Tracks
/var/log/syslogGeneral system events (Ubuntu/Debian)
/var/log/messagesGeneral system events (Rocky/AlmaLinux)
/var/log/auth.logSSH logins, sudo usage, authentication (Ubuntu/Debian)
/var/log/secureSSH logins, sudo usage, authentication (Rocky/AlmaLinux)
/var/log/nginx/access.logEvery HTTP request to Nginx
/var/log/nginx/error.logNginx errors (misconfigs, upstream failures)
/var/log/apache2/access.logEvery HTTP request to Apache (Ubuntu/Debian)
/var/log/httpd/access_logEvery HTTP request to Apache (Rocky/AlmaLinux)
/var/log/apache2/error.logApache errors (Ubuntu/Debian)
/var/log/httpd/error_logApache errors (Rocky/AlmaLinux)
/var/log/mysql/error.logMySQL/MariaDB errors and warnings
/var/log/php*-fpm.logPHP-FPM errors (pool issues, crashes)
/var/log/fail2ban.logFail2Ban bans and unbans
/var/log/mail.logMail server activity (Postfix, Dovecot)
/var/log/cronCron job execution (Rocky/AlmaLinux)

Basic Log Commands

View a Log File

  # Print the entire log (not recommended for large files)
cat /var/log/syslog

# View the last 50 lines
tail -50 /var/log/syslog

# Follow a log in real time (Ctrl+C to stop)
tail -f /var/log/syslog

# Follow multiple logs simultaneously
tail -f /var/log/nginx/access.log /var/log/nginx/error.log

# Scroll through a log interactively (press q to quit)
less /var/log/syslog
# Tip: press Shift+F in less to follow like tail -f
  

Search Within Logs

  # Find lines containing a keyword
grep "error" /var/log/syslog

# Case-insensitive search
grep -i "failed" /var/log/auth.log

# Show 3 lines before and after each match (context)
grep -B3 -A3 "OOM" /var/log/syslog

# Count occurrences
grep -c "Failed password" /var/log/auth.log

# Search across multiple log files
grep -r "502 Bad Gateway" /var/log/nginx/

# Exclude patterns
grep -v "GET /health" /var/log/nginx/access.log
  

Filter by Time

  # Lines from a specific date
grep "Apr 12" /var/log/syslog

# Lines from the last hour (using awk with timestamps)
awk -v d="$(date -d '1 hour ago' '+%b %d %H')" '$0 >= d' /var/log/syslog
  

Using journalctl (systemd)

Modern Linux distributions use systemd-journald as the primary logging system. journalctl is its powerful query tool.

  # View all logs (newest last)
journalctl

# Follow in real time
journalctl -f

# Logs from a specific service
journalctl -u nginx
journalctl -u mysql
journalctl -u php8.2-fpm

# Logs from the last hour
journalctl --since "1 hour ago"

# Logs from a specific time range
journalctl --since "2026-04-12 14:00" --until "2026-04-12 16:00"

# Logs since last boot
journalctl -b

# Only error messages and above
journalctl -p err

# Kernel messages only
journalctl -k

# Show logs in reverse (newest first)
journalctl -r

# Output as JSON (useful for parsing)
journalctl -u nginx --output=json-pretty --since "1 hour ago"
  

Priority Levels

The -p flag filters by severity:

LevelNameWhat It Means
0emergSystem is unusable
1alertAction must be taken immediately
2critCritical conditions
3errError conditions
4warningWarning conditions
5noticeNormal but significant events
6infoInformational messages
7debugDebug-level messages
  # Show everything from "warning" and above
journalctl -p warning

# Show only critical and emergency
journalctl -p crit
  

Analyzing Web Server Logs

Nginx / Apache Access Log Format

A typical access log line looks like this:

  203.0.113.50 - - [12/Apr/2026:14:32:11 +0000] "GET /wp-login.php HTTP/1.1" 200 4523 "-" "Mozilla/5.0..."
  
FieldMeaning
203.0.113.50Client IP address
[12/Apr/2026:14:32:11 +0000]Timestamp
GET /wp-login.php HTTP/1.1Request method, path, and protocol
200HTTP status code
4523Response size in bytes
Mozilla/5.0...User agent string

Useful One-Liners

  # Top 20 IPs by request count
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# Top 20 most requested URLs
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# All 404 errors
awk '$9 == 404' /var/log/nginx/access.log

# All 500 errors (server errors)
awk '$9 == 500' /var/log/nginx/access.log

# Requests per hour (traffic pattern)
awk '{print $4}' /var/log/nginx/access.log | cut -d: -f1-2 | sort | uniq -c

# Requests to wp-login.php (potential brute force)
grep "wp-login.php" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# Bandwidth usage per IP (top consumers)
awk '{ip[$1]+=$10} END {for (i in ip) print ip[i], i}' /var/log/nginx/access.log | sort -rn | head -20

# All requests from a specific IP
grep "203.0.113.50" /var/log/nginx/access.log
  

Identify Attacks and Abuse

  # Brute force attempts on SSH
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10

# WordPress login brute force
grep "POST /wp-login.php" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

# Suspicious URL patterns (SQL injection, path traversal)
grep -E "(union|select|\.\.\/|etc\/passwd|<script)" /var/log/nginx/access.log

# Bot traffic
grep -i "bot\|crawler\|spider" /var/log/nginx/access.log | wc -l

# Check who Fail2Ban has blocked
sudo fail2ban-client status sshd
grep "Ban" /var/log/fail2ban.log | tail -20
  

Analyzing PHP-FPM Logs

PHP-FPM logs reveal application crashes, memory issues, and timeout problems:

  # Find the PHP-FPM log file
ls /var/log/php*

# Common error patterns
grep "FATAL" /var/log/php8.2-fpm.log
grep "WARNING" /var/log/php8.2-fpm.log
grep "child" /var/log/php8.2-fpm.log       # process crashes
grep "memory" /var/log/php8.2-fpm.log       # memory exhaustion

# Enable slow query logging in PHP-FPM
# Edit your pool config (e.g., /etc/php/8.2/fpm/pool.d/www.conf)
# slowlog = /var/log/php8.2-fpm-slow.log
# request_slowlog_timeout = 5s
  

Analyzing MySQL / MariaDB Logs

  # Error log (crashes, startup issues)
tail -50 /var/log/mysql/error.log

# Enable and view the slow query log
# In /etc/mysql/mysql.conf.d/mysqld.cnf:
# slow_query_log = 1
# slow_query_log_file = /var/log/mysql/slow.log
# long_query_time = 2

# View slow queries
tail -50 /var/log/mysql/slow.log

# Most frequently slow queries
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log
  

Live Monitoring

Watch Multiple Logs at Once

  # Using multitail (install it first)
sudo apt install multitail -y    # Ubuntu/Debian
sudo dnf install multitail -y    # Rocky/AlmaLinux

# Watch Nginx access and error logs side by side
multitail /var/log/nginx/access.log /var/log/nginx/error.log

# Mix system and application logs
multitail /var/log/syslog /var/log/nginx/error.log /var/log/mysql/error.log
  

Real-Time HTTP Status Monitoring

  # Watch HTTP status codes in real time
tail -f /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c

# Color-coded real-time log viewer
tail -f /var/log/nginx/access.log | \
  awk '{
    if ($9 >= 500) printf "\033[31m%s\033[0m\n", $0;       # Red for 5xx
    else if ($9 >= 400) printf "\033[33m%s\033[0m\n", $0;   # Yellow for 4xx
    else if ($9 >= 300) printf "\033[36m%s\033[0m\n", $0;   # Cyan for 3xx
    else printf "\033[32m%s\033[0m\n", $0;                   # Green for 2xx
  }'
  

Log Management Best Practices

  1. Set up log rotation - Don’t let logs grow forever. See our Disk Management Guide for logrotate configuration.

  2. Keep logs for at least 14 days - You need enough history to diagnose recurring issues, but not so much that it fills your disk.

  3. Limit journal size - Add SystemMaxUse=200M to /etc/systemd/journald.conf.

  4. Centralize logs for critical servers - For production environments, consider forwarding logs to a remote syslog server or a service like Grafana Loki.

  5. Monitor, don’t just read - Set up alerts for critical patterns:

  # Simple alert: email on any 500 error
tail -F /var/log/nginx/error.log | grep --line-buffered "500" | while read line; do
    echo "$line" | mail -s "500 Error Alert" admin@yourdomain.com
done &
  

Troubleshooting

ProblemFix
Log file is emptyThe service may log to journal instead. Check with journalctl -u servicename.
Log file doesn’t existThe service may not be installed, or the log path is different. Check the service config for the error_log or ErrorLog directive.
Logs are too big to openUse tail, less, or grep instead of cat. For analysis, use awk one-liners.
Can’t read logs - permission deniedMost logs require root. Use sudo.
Old logs are missingLog rotation is removing them. Check /etc/logrotate.d/ for retention settings.
journalctl shows very littleThe journal may not persist across reboots. Run sudo mkdir -p /var/log/journal && sudo systemctl restart systemd-journald to enable persistence.
Nginx access log shows internal IPs (127.0.0.1)You’re behind a reverse proxy or load balancer. Configure real_ip in Nginx to log the client’s actual IP.

Last updated 21 Apr 2026, 08:08 +0300. history

Was this page helpful?