Nginx Log Analizi: Access ve Error Log Okuma
Bir production sunucusunda bir şeyler ters gittiğinde, ilk bakacağın yer loglar olmalı. Nginx logları, sunucunuzda neler döndüğünü anlamak için altın değerinde bir kaynak. Ama ham haliyle binlerce satır log dosyasına bakmak, samanlıkta iğne aramak gibi hissettiriyor. Bu yazıda Nginx access ve error loglarını nasıl okuyacağınızı, anlamlı veriler nasıl çıkaracağınızı ve gerçek dünya senaryolarında nasıl hata ayıklayacağınızı detaylıca ele alacağız.
Nginx Log Dosyaları Nerede?
Önce temel soruyu cevaplayalım: loglar nerede? Nginx’in varsayılan kurulumunda log dosyaları genellikle şu konumlarda bulunur:
- /var/log/nginx/access.log: Tüm HTTP isteklerinin kaydı
- /var/log/nginx/error.log: Hata mesajları ve uyarılar
- /etc/nginx/nginx.conf: Log formatı ve yolları burada tanımlanır
Eğer sanal host (virtual host) kullanıyorsanız, her site için ayrı log dosyaları olabilir:
# Mevcut log dosyalarını bul
find /var/log/nginx/ -name "*.log" -type f
ls -lh /var/log/nginx/
# Nginx konfigürasyonunda log yollarını kontrol et
grep -r "access_log|error_log" /etc/nginx/
Access Log Format Anatomisi
Nginx’in varsayılan access log formatı olan combined formatını anlamak, log analizinin temelidir.
Tipik bir access log satırı şöyle görünür:
192.168.1.100 - john [10/Dec/2024:14:23:45 +0300] "GET /api/users HTTP/1.1" 200 1234 "https://example.com" "Mozilla/5.0 (Windows NT 10.0)"
Bu satırdaki her alan sırasıyla şu anlama gelir:
- $remote_addr: İstemcinin IP adresi (192.168.1.100)
- $remote_user: HTTP auth kullanan kullanıcı adı, yoksa tire (-)
- $time_local: İsteğin zamanı
- $request: HTTP metodu, URL ve protokol
- $status: HTTP durum kodu (200)
- $body_bytes_sent: Gönderilen byte miktarı
- $http_referer: Kullanıcının geldiği sayfa
- $http_user_agent: Tarayıcı/istemci bilgisi
Kendi log formatınızı nginx.conf içinde tanımlayabilirsiniz:
# /etc/nginx/nginx.conf
http {
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time';
access_log /var/log/nginx/access.log detailed;
error_log /var/log/nginx/error.log warn;
}
$request_time ve $upstream_response_time alanlarını eklemek, yavaş istekleri tespit etmek için son derece faydalı. Bunu mutlaka log formatınıza dahil edin.
Canlı Log Takibi
Production ortamında en sık kullandığım komutlardan biri tail ile canlı log izlemektir:
# Canlı access log takibi
tail -f /var/log/nginx/access.log
# Hem access hem error logu aynı anda takip et
tail -f /var/log/nginx/access.log /var/log/nginx/error.log
# Sadece 500 hatalarını canlı izle
tail -f /var/log/nginx/access.log | grep ' 500 '
# Belirli bir IP'nin isteklerini canlı izle
tail -f /var/log/nginx/access.log | grep '192.168.1.100'
Bir müşteri “site çöktü” diye aradığında, ilk açtığım terminal penceresi bu komutları çalıştırır. Canlı akışa bakarak durumu hızlıca değerlendiriyorum.
Error Log Seviyeleri
Nginx error logları farklı seviyelerde mesaj kaydeder. Bu seviyeleri anlamak, hangi mesajların kritik olduğunu ayırt etmenizi sağlar:
- emerg: Sunucu kullanılamaz hale geldi, en kritik seviye
- alert: Hemen müdahale gerektiren durum
- crit: Kritik hata koşulları
- error: Hata mesajları, servis etkilenmiş olabilir
- warn: Uyarı mesajları, dikkat edilmeli
- notice: Normal ama önemli durum bildirimleri
- info: Bilgi mesajları
- debug: Detaylı debug bilgisi, sadece geliştirme ortamında açın
Konfigürasyonda log seviyesini ayarlamak:
# Sadece error ve üstü seviyeleri kaydet
error_log /var/log/nginx/error.log error;
# Debug modu (üretimde KULLANMAYIN, disk dolabilir)
error_log /var/log/nginx/error.log debug;
Temel Log Analizi Komutları
Şimdi işin pratik kısmına geçelim. Bash araçlarıyla loglardan anlamlı bilgiler çıkarmak:
# Toplam istek sayısı
wc -l /var/log/nginx/access.log
# HTTP durum kodlarına göre dağılım
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
# En çok istek yapan IP'ler (Top 10)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
# En çok erişilen URL'ler
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
# 404 hatası veren URL'ler
grep ' 404 ' /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
# Belirli bir zaman aralığındaki istekler
grep "10/Dec/2024:14:" /var/log/nginx/access.log | wc -l
Bu komutları sıklıkla kullanıyorum. Özellikle “hangi sayfalar 404 veriyor” sorusu, broken link tespiti için çok işlevsel.
Yavaş İstek Tespiti
Eğer log formatınıza $request_time eklediyseniz, yavaş istekleri tespit etmek kolaylaşır:
# 3 saniyeden uzun süren istekleri bul
awk '$(NF) > 3 {print}' /var/log/nginx/access.log
# En yavaş 10 isteği listele (son alan request_time ise)
awk '{print $NF, $7}' /var/log/nginx/access.log | sort -rn | head -10
# Ortalama yanıt süresi hesapla
awk '{sum += $NF; count++} END {print "Ortalama:", sum/count, "saniye"}' /var/log/nginx/access.log
Geçen ay bir e-ticaret sitesinde checkout sayfasının neden yavaş çalıştığını araştırıyordum. Bu komutla baktığımda, bir API endpoint’inin ortalama 8 saniye yanıt verdiğini gördüm. Backend ekibine direkt kanıtı sunabilmek çok kolaylaştırdı iletişimi.
Gerçek Dünya Senaryosu 1: DDoS veya Brute Force Tespiti
Aniden sunucu yükü arttığında ve access log’a baktığınızda belirli bir IP’den binlerce istek görüyorsunuz:
# Son 1000 satırda IP başına istek sayısı
tail -1000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn
# Belirli bir IP'nin hangi URL'lere istek yaptığını gör
grep '185.220.101.45' /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn
# Dakika başına istek sayısı (flooding var mı?)
awk '{print $4}' /var/log/nginx/access.log | cut -c2-18 | sort | uniq -c | sort -rn | head -20
Bu şüpheli IP’yi nginx konfigürasyonuyla veya iptables ile engelleyebilirsiniz:
# iptables ile hızlı engelleme
iptables -I INPUT -s 185.220.101.45 -j DROP
# Nginx konfigürasyonunda engelleme (nginx.conf veya site konfigürasyonu)
# location / { deny 185.220.101.45; allow all; }
# Engelleme sonrası nginx'i reload et
nginx -t && systemctl reload nginx
Gerçek Dünya Senaryosu 2: Error Log’dan 502 Bad Gateway Hatasını Çözmek
502 hataları PHP-FPM veya upstream backend sorunlarından kaynaklanır. Error log bu durumda çok bilgi verir:
# Son 502 hatalarını error logdan bul
grep "502" /var/log/nginx/error.log | tail -50
# PHP-FPM bağlantı hatalarını ara
grep "connect() failed|no live upstreams|upstream timed out" /var/log/nginx/error.log | tail -20
# Hataların zaman dağılımını gör
grep "upstream timed out" /var/log/nginx/error.log | awk '{print $1, $2}' | sort | uniq -c
Tipik bir 502 error log mesajı şöyle görünür:
2024/12/10 14:23:45 [error] 1234#1234: *56789 connect() failed (111: Connection refused)
while connecting to upstream, client: 192.168.1.100, server: example.com,
request: "POST /api/process HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000"
Bu mesajı gördüğünüzde hemen PHP-FPM servisini kontrol edin:
# PHP-FPM durumunu kontrol et
systemctl status php8.1-fpm
# PHP-FPM loglarına bak
tail -50 /var/log/php8.1-fpm.log
# PHP-FPM process sayısını kontrol et
ps aux | grep php-fpm | wc -l
Gerçek Dünya Senaryosu 3: Disk Dolunca Log Yönetimi
Log dosyaları hızla büyüyebilir. Birkaç hafta önce bir sunucuda /var/log partisyonu dolmuş ve nginx yeni log yazamaz hale gelmişti:
# Log dosyasının boyutunu kontrol et
ls -lh /var/log/nginx/access.log
du -sh /var/log/nginx/
# Disk kullanımını genel olarak kontrol et
df -h /var/log
# Büyük log dosyalarını bul
find /var/log -name "*.log" -size +100M -ls
# Acil durumda log dosyasını truncate et (silme, truncate!)
# ÖNCE BACKUP AL!
cp /var/log/nginx/access.log /tmp/access.log.backup
> /var/log/nginx/access.log
# Nginx'i logrotate için sinyal gönder
kill -USR1 $(cat /var/run/nginx.pid)
Logrotate konfigürasyonunu mutlaka ayarlayın:
# /etc/logrotate.d/nginx dosyasını kontrol et
cat /etc/logrotate.d/nginx
# Örnek logrotate konfigürasyonu
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
GoAccess ile Görsel Log Analizi
Komut satırını seven biri olsam da, bazen görsel bir rapor çok işlevsel oluyor. GoAccess tam bu iş için:
# GoAccess kurulumu (Ubuntu/Debian)
apt install goaccess
# Terminal üzerinde interaktif analiz
goaccess /var/log/nginx/access.log --log-format=COMBINED
# HTML rapor oluştur
goaccess /var/log/nginx/access.log --log-format=COMBINED -o /var/www/html/report.html
# Birden fazla log dosyasını birleştirerek analiz et
cat /var/log/nginx/access.log /var/log/nginx/access.log.1 | goaccess --log-format=COMBINED
# Canlı HTML rapor (websocket ile güncellenen)
goaccess /var/log/nginx/access.log --log-format=COMBINED
--real-time-html -o /var/www/html/live-report.html
--daemonize --ws-url=ws://yourdomain.com:7890
GoAccess size şunları verir: en çok ziyaret edilen sayfalar, benzersiz ziyaretçi sayısı, bant genişliği kullanımı, 404 hataları, tarayıcı ve işletim sistemi dağılımı. Müşteriye aylık rapor hazırlarken bu HTML çıktısını doğrudan gönderiyorum.
Log Analizinde Pratik Grep Teknikleri
# Belirli bir tarih aralığındaki hataları filtrele
grep "10/Dec/2024" /var/log/nginx/error.log | grep "[error]"
# User agent'a göre bot trafiğini tespit et
grep -i "bot|crawler|spider" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn
# POST isteklerini listele (form saldırısı tespiti)
grep '"POST ' /var/log/nginx/access.log | awk '{print $1, $7}' | sort | uniq -c | sort -rn | head -20
# Sadece başarılı istekleri say (2xx kodları)
grep ' 2[0-9][0-9] ' /var/log/nginx/access.log | wc -l
# Yönlendirme (3xx) sayısı
grep ' 3[0-9][0-9] ' /var/log/nginx/access.log | wc -l
# Sunucu hatası (5xx) sayısı ve içeriği
grep ' 5[0-9][0-9] ' /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c
# Belirli bir saatte ne kadar trafik geldi
grep "10/Dec/2024:15:" /var/log/nginx/access.log | wc -l
Nginx Debug Log’u Açmak
Özellikle karmaşık rewrite kuralları veya proxy konfigürasyonlarında debug log’u açmak gerekebilir:
# nginx.conf veya site konfigürasyonunda
error_log /var/log/nginx/debug.log debug;
# Sadece belirli bir connection için debug
events {
debug_connection 192.168.1.100;
}
Uyarı: Debug modu çok fazla log üretir. Üretim ortamında sadece kısa süreliğine ve belirli bir IP için açın. 15-20 dakika sonra mutlaka kapatın, yoksa disk dolabilir.
# Debug logunu açtıktan sonra test et
nginx -t && systemctl reload nginx
# Debug logunu izle
tail -f /var/log/nginx/debug.log | grep "rewrite|location"
# İşin bitince debug'ı kapat ve reload et
# error_log /var/log/nginx/error.log warn; # satırını geri al
nginx -t && systemctl reload nginx
Sık Karşılaşılan Error Log Mesajları ve Anlamları
Nginx error loglarında sürekli karşılaştığım mesajlar ve ne yapmanız gerektiği:
- “connect() failed (111: Connection refused)”: Upstream (PHP-FPM, Node.js vb.) çalışmıyor. Upstream servisini başlatın.
- “no live upstreams while connecting to upstream”: Tüm upstream sunucular yanıt vermiyor. Upstream konfigürasyonunu ve servisleri kontrol edin.
- “client intended to send too large body”: İstemci büyük dosya gönderiyor.
client_max_body_sizedeğerini artırın. - “could not build server_names_hash”: server_names_hash_bucket_size küçük. nginx.conf’ta artırın.
- “too many open files”: Sistem file descriptor limiti dolmuş. ulimit ve nginx worker_rlimit_nofile değerlerini artırın.
- “SSL_do_handshake() failed”: SSL/TLS handshake hatası. Sertifikayı ve SSL konfigürasyonunu kontrol edin.
- “permission denied”: Nginx dosyaya/sokete erişemiyor. Dosya izinlerini kontrol edin.
Otomatik Log Analiz Scripti
Her sabah çalıştırdığım basit bir bash scripti:
#!/bin/bash
# nginx-log-summary.sh
# Her gün çalıştır: 0 8 * * * /usr/local/bin/nginx-log-summary.sh
LOG="/var/log/nginx/access.log"
DATE=$(date '+%d/%b/%Y')
EMAIL="[email protected]"
echo "=== Nginx Gunluk Ozet - $DATE ===" > /tmp/nginx-summary.txt
echo "" >> /tmp/nginx-summary.txt
echo "Toplam Istek Sayisi:" >> /tmp/nginx-summary.txt
grep "$DATE" $LOG | wc -l >> /tmp/nginx-summary.txt
echo "" >> /tmp/nginx-summary.txt
echo "HTTP Durum Kodu Dagilimi:" >> /tmp/nginx-summary.txt
grep "$DATE" $LOG | awk '{print $9}' | sort | uniq -c | sort -rn >> /tmp/nginx-summary.txt
echo "" >> /tmp/nginx-summary.txt
echo "En Cok Istek Yapan 10 IP:" >> /tmp/nginx-summary.txt
grep "$DATE" $LOG | awk '{print $1}' | sort | uniq -c | sort -rn | head -10 >> /tmp/nginx-summary.txt
echo "" >> /tmp/nginx-summary.txt
echo "En Cok 404 Veren URL'ler:" >> /tmp/nginx-summary.txt
grep "$DATE" $LOG | grep ' 404 ' | awk '{print $7}' | sort | uniq -c | sort -rn | head -10 >> /tmp/nginx-summary.txt
echo "" >> /tmp/nginx-summary.txt
echo "500 Hata Sayisi:" >> /tmp/nginx-summary.txt
grep "$DATE" $LOG | grep ' 5[0-9][0-9] ' | wc -l >> /tmp/nginx-summary.txt
# Eposta gonder
mail -s "Nginx Gunluk Ozet - $DATE" $EMAIL < /tmp/nginx-summary.txt
echo "Ozet olusturuldu ve gonderildi."
Bu scripti crontab’a ekleyip her gün sabah 8’de çalıştırıyorum. Kahve içerken sunucu durumunu e-postadan kontrol etmek güzel bir alışkanlık.
Sonuç
Nginx log analizi, sistem yöneticiliğinin temel becerilerinden biri. Access log’dan gelen trafik örüntüsünü anlamak, error log’dan hataları tespit etmek ve bu bilgileri hızlıca eyleme dönüştürmek; hem güvenlik hem de performans açısından kritik önem taşıyor.
Öğrendiklerimizi özetleyecek olursak:
- Log formatını özelleştirerek $request_time ve $upstream_response_time alanlarını her zaman ekleyin
tail -file canlı izleme, sorun anında ilk refleksiniz olsunawk,grep,sort,uniqkombinasyonu ile log’lardan hızla istatistik çıkarabilirsiniz- GoAccess ile görsel raporlar oluşturabilirsiniz
- Debug log’u sadece gerektiğinde ve kısa süreliğine açın
- Logrotate konfigürasyonunu mutlaka yapın, diskiniz teşekkür eder
Pratik yapmak için kendi test ortamınızda bu komutları deneyin. Log okuma bir alışkanlık meselesi; ne kadar çok bakarsanız, anormalliği o kadar hızlı fark edersiniz. Bir süre sonra log satırlarına bakıp “burada bir şeyler yanlış” duygusu geliştirmeye başlayacaksınız, bu da iyi bir sistem yöneticisinin en değerli özelliklerinden biri.
