Logi serwera Apache i Nginx — jak czytać i analizować
Gdzie są pliki logów?
Logi serwera to pierwsze miejsce, które należy sprawdzić gdy strona zwraca błędy lub działa wolno. Zawierają zapis każdego żądania HTTP i szczegóły błędów serwera.
Powiązane tematy: konfiguracja Nginx vhost, UFW firewall, SSH keys na VPS oraz backup strategia. Do wyboru odpowiedniego serwera VPS użyj kalkulatora kosztów.
| Serwer | Access log | Error log |
|---|---|---|
| Apache (Debian/Ubuntu) | /var/log/apache2/access.log | /var/log/apache2/error.log |
| Apache (CentOS/RHEL) | /var/log/httpd/access_log | /var/log/httpd/error_log |
| Nginx | /var/log/nginx/access.log | /var/log/nginx/error.log |
| Per vhost (Apache) | /var/log/apache2/example.com-access.log | /var/log/apache2/example.com-error.log |
| Per vhost (Nginx) | /var/log/nginx/example.com.access.log | /var/log/nginx/example.com.error.log |
Format logów — Combined Log Format
Apache i Nginx domyślnie używają Combined Log Format:
127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.1" 200 2326 "http://www.example.com/start.html" "Mozilla/5.0..."
| | | | | | | | |
IP | | timestamp request status size referrer user-agent
| user (- = brak)
ident (- = brak) Kody statusu HTTP:
| Kod | Znaczenie | Co robić |
|---|---|---|
| 200 | OK — żądanie obsłużone | Normalny ruch |
| 301/302 | Przekierowanie | Sprawdź pętle redirectów |
| 304 | Not Modified (cache) | Cache działa poprawnie |
| 400 | Bad Request | Nieprawidłowe żądanie klienta |
| 403 | Forbidden | Uprawnienia plików, .htaccess |
| 404 | Not Found | Brakujące zasoby, broken links |
| 429 | Too Many Requests | Rate limiting aktywny |
| 500 | Internal Server Error | Sprawdź error.log natychmiast |
| 502 | Bad Gateway | PHP-FPM/backend nie odpowiada |
| 503 | Service Unavailable | Serwer przeciążony |
Podstawowe komendy — szybka analiza
# Ostatnie 50 wierszy access logu (live)
tail -f /var/log/nginx/access.log
# Wszystkie błędy 500
grep ' 500 ' /var/log/nginx/access.log
# Top 10 najczęściej żądanych URLi
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head 10
# Top 10 adresów IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head 10
# Wszystkie błędy 404 (brakujące pliki)
grep ' 404 ' /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head 20
# Żądania z konkretnego IP
grep '^192.168.1.100' /var/log/nginx/access.log
# Ruch z bota / crawlera
grep -i 'googlebot\|bingbot\|semrush\|ahrefs' /var/log/nginx/access.log | wc -l Error log — jak czytać błędy
Nginx error log
2024/01/15 12:34:56 [error] 1234#0: *567 connect() failed (111: Connection refused)
| | |
timestamp level PID#TID connection_id błąd
Poziomy błędów Nginx: debug → info → notice → warn → error → crit → alert → emerg
Apache error log
[Mon Jan 15 12:34:56.789012 2024] [php:error] [pid 1234] [client 1.2.3.4:56789]
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted in /var/www/wp-content/plugins/... Typowe błędy i znaczenie
# PHP-FPM nie odpowiada (Nginx)
connect() failed (111: Connection refused) while connecting to upstream
# Zbyt mało pamięci PHP
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
# Brak uprawnień do pliku
Permission denied: '/var/www/html/.htaccess'
# Przekroczony limit czasu PHP
PHP Fatal error: Maximum execution time of 30 seconds exceeded
# Błąd SSL
SSL_do_handshake() failed (SSL: error:1408F10B)
# Zbyt wiele otwartych połączeń
worker_connections are not enough GoAccess — wizualna analiza logów w terminalu
GoAccess to narzędzie open-source do analizy logów w czasie rzeczywistym — działa w terminalu i generuje raporty HTML.
# Instalacja
sudo apt install goaccess
# Analiza w terminalu (interactive)
goaccess /var/log/nginx/access.log --log-format=COMBINED
# Generowanie raportu HTML
goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED
# Analiza wielu plików (z rotacją logów)
zcat /var/log/nginx/access.log.*.gz | goaccess - --log-format=COMBINED -o report.html
# Live streaming do HTML przez WebSocket
goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED --real-time-html GoAccess pokazuje: top strony, top IP, kody statusu, przeglądarki, systemy operacyjne, bandwidth, rozkład godzinowy.
Fail2ban — blokowanie złośliwych IP na podstawie logów
Fail2ban czyta logi i automatycznie banuje IP przekraczające limity błędów (np. zbyt wiele 404, próby logowania):
sudo apt install fail2ban
# Konfiguracja dla Nginx
cat /etc/fail2ban/jail.local [nginx-http-auth]
enabled = true
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
bantime = 3600
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
bantime = 600 sudo systemctl restart fail2ban
# Sprawdź zbanowane IP
sudo fail2ban-client status nginx-http-auth
# Odbanuj IP
sudo fail2ban-client set nginx-http-auth unbanip 1.2.3.4 Rotacja logów — logrotate
Pliki logów rosną — logrotate automatycznie archiwizuje i kompresuje stare logi.
Nginx i Apache instalują własne konfiguracje w /etc/logrotate.d/:
# Typowa konfiguracja /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily # rotuj codziennie
missingok # nie błądź jeśli brak pliku
rotate 14 # przechowaj 14 wersji
compress # kompresuj do .gz
delaycompress # kompresuj poprzedni, nie obecny
notifempty # nie rotuj pustego pliku
sharedscripts
postrotate
nginx -s reopen # poinformuj Nginx o nowym pliku
endscript
} # Ręczne wymuszenie rotacji (test)
sudo logrotate -f /etc/logrotate.d/nginx
# Lista skompresowanych logów
ls -lh /var/log/nginx/ Diagnostyka problemów — checklist
- Strona zwraca 500:
tail -50 /var/log/nginx/error.log # Szukaj ostatnich wpisów PHP Fatal error lub connect() failed - Strona wolna:
# Sprawdź czy PHP-FPM nie jest przeciążony grep 'upstream timed out' /var/log/nginx/error.log | wc -l - Wysoki ruch z jednego IP (atak):
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head 5 # Zbanuj ręcznie iptables -I INPUT -s 1.2.3.4 -j DROP - Sprawdź ruch w czasie:
# Ile żądań na minutę teraz tail -1000 /var/log/nginx/access.log | awk '{print $4}' | cut -d: -f2 | uniq -c