Nginx Debug Modu: error_log Debug Seviyesi ile Hata Ayıklama
Nginx üzerinde garip bir şey oluyor, istekler düzgün gitmiyor, upstream bağlantıları kesiliyor ya da bir location bloğu beklendiği gibi çalışmıyor. Normal log seviyeleri sana yeterli bilgiyi vermiyor. İşte bu noktada error_log direktifinin debug seviyesi devreye giriyor. Bu yazıda Nginx’in debug log modunu en ince ayrıntısına kadar ele alacağız.
Nginx Log Seviyeleri Hiyerarşisi
Nginx’te error_log direktifi birden fazla log seviyesini destekler. Bu seviyeler aşağıdan yukarıya doğru giderek daha az ayrıntı içerir:
- debug: Her şeyi loglar, en ayrıntılı seviye
- info: Genel bilgi mesajları
- notice: Önemli ama hata olmayan olaylar
- warn: Uyarılar
- error: Hatalar (varsayılan davranışa en yakın)
- crit: Kritik hatalar
- alert: Acil müdahale gerektiren durumlar
- emerg: Sistem kullanılamaz hale geldi
Bir seviye seçtiğinde, o seviye ve üzeri tüm mesajlar loglanır. Yani warn seçersen warn, error, crit, alert ve emerg mesajlarını görürsün. debug seçersen gerçekten her şeyi görürsün.
Debug Modunu Aktif Etmek için Nginx Derleme Şartı
Burada kritik bir nokta var: Nginx’i debug moduyla kullanmak için binary’nin --with-debug flag’iyle derlenmiş olması gerekiyor. Bu flag olmadan error_log direktifine debug yazsanbile hiçbir şey olmaz.
Kurulu Nginx’in debug desteğiyle gelip gelmediğini kontrol etmek için:
nginx -V 2>&1 | grep -- '--with-debug'
Eğer çıktıda --with-debug görüyorsan hazırsın. Görmüyorsan birkaç seçeneğin var:
Ubuntu/Debian için:
apt-get install nginx-debug
Bu paket, /usr/sbin/nginx-debug binary’sini kurar. Aynı config dosyalarını kullanır, sadece binary farklıdır.
CentOS/RHEL için resmi Nginx repo’sundan:
yum install nginx-debug
# veya
dnf install nginx-debug
Manuel derleme tercih ediyorsan:
./configure --with-debug --with-http_ssl_module --with-http_v2_module
--prefix=/etc/nginx --sbin-path=/usr/sbin/nginx
--modules-path=/usr/lib64/nginx/modules
--conf-path=/etc/nginx/nginx.conf
--error-log-path=/var/log/nginx/error.log
--http-log-path=/var/log/nginx/access.log
--pid-path=/var/run/nginx.pid
make && make install
Temel Konfigürasyon
Debug loglamayı açmanın en basit yolu nginx.conf dosyasındaki error_log direktifini güncellemek:
# /etc/nginx/nginx.conf
error_log /var/log/nginx/error.log debug;
events {
worker_connections 1024;
}
http {
# ...
}
Bu ayar global seviyede tüm trafiği debug modda loglar. Dikkat: Production’da bunu yapmak log dosyasını çok hızlı büyütür ve disk I/O’yu ciddi şekilde artırır. Yüksek trafikli bir sunucuda dakikalar içinde GB’larca log üretebilirsin.
nginx-debug binary kullanıyorsan servisi şöyle başlatabilirsin:
# Önce normal nginx'i durdur
systemctl stop nginx
# Debug binary'yi başlat
nginx-debug -c /etc/nginx/nginx.conf
# Veya systemd ile
service nginx-debug start
Logları gerçek zamanlı takip etmek için:
tail -f /var/log/nginx/error.log | grep -v "^$"
Belirli IP İçin Debug Loglama
Production ortamında en güvenli yöntem sadece belirli bir IP adresinden gelen istekler için debug loglamayı aktif etmektir. Bu sayede diğer kullanıcılar etkilenmez ve log dosyası kontrolsüz büyümez.
# /etc/nginx/nginx.conf
error_log /var/log/nginx/error.log;
events {
worker_connections 1024;
debug_connection 192.168.1.50;
debug_connection 10.0.0.0/24;
}
debug_connection direktifi events bloğu içinde tanımlanır ve IP adresi veya CIDR notasyonu kabul eder. Bu yöntemi kullandığında global error_log seviyesi ne olursa olsun, belirtilen IP’lerden gelen bağlantılar için debug mesajları üretilir.
Birden fazla IP veya subnet tanımlayabilirsin:
events {
worker_connections 1024;
debug_connection 192.168.1.50; # Geliştirici bilgisayarı
debug_connection 10.10.0.0/16; # İç ağ
debug_connection 172.16.5.100; # Test sunucusu
}
Virtual Host Bazlı Debug Loglama
Her server bloğu için ayrı debug log dosyası tanımlamak izolasyon açısından çok işe yarıyor:
http {
# Genel log seviyesi normal kalsın
error_log /var/log/nginx/error.log warn;
server {
listen 80;
server_name app.example.com;
# Sadece bu virtual host için debug
error_log /var/log/nginx/app_debug.log debug;
location / {
proxy_pass http://backend;
}
}
server {
listen 80;
server_name static.example.com;
# Bu server normal log seviyesini kullanır
root /var/www/static;
}
}
Bu konfigürasyonla app.example.com‘a gelen tüm istekler /var/log/nginx/app_debug.log dosyasına debug seviyesinde loglanırken diğer server blokları etkilenmez.
Gerçek Dünya Senaryosu 1: Upstream Bağlantı Sorunları
Diyelim ki bir reverse proxy kurulumunda upstream sunucuya zaman zaman bağlanamıyorsun ama hata mesajı yeterince açıklayıcı değil. Debug logu bu durumda altın değerinde:
upstream backend_pool {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
error_log /var/log/nginx/api_debug.log debug;
location /api/ {
proxy_pass http://backend_pool;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_connect_timeout 5s;
proxy_read_timeout 30s;
}
}
Debug logunda şunları arayabilirsin:
# Upstream seçim kararlarını gör
grep "upstream" /var/log/nginx/api_debug.log | grep -E "trying|next"
# Keepalive bağlantı durumunu kontrol et
grep "keepalive" /var/log/nginx/api_debug.log
# Bağlantı hatalarını filtrele
grep "connect() failed|upstream timed out" /var/log/nginx/api_debug.log
Debug logda tipik bir upstream seçim akışı şöyle görünür:
2024/01/15 14:23:41 [debug] 12345#0: *1 upstream: found 0 live connections
2024/01/15 14:23:41 [debug] 12345#0: *1 upstream: trying to reuse keepalive connection
2024/01/15 14:23:41 [debug] 12345#0: *1 upstream: keepalive connection is reused
Bağlantı sorunu varsa şunu görürsün:
2024/01/15 14:23:42 [debug] 12345#0: *2 upstream: next upstream
2024/01/15 14:23:42 [error] 12345#0: *2 connect() failed (111: Connection refused)
Gerçek Dünya Senaryosu 2: Location Bloğu Eşleşme Sorunları
Bir müşterim location bloklarının beklenmedik şekilde çalıştığından şikayet etti. Regex location’ları ile prefix location’ları çakışıyordu. Debug log bu durumu çözmekte son derece etkili:
server {
listen 80;
server_name example.com;
error_log /var/log/nginx/location_debug.log debug;
location /api {
proxy_pass http://api_backend;
}
location ~* ^/api/v2/(.*)$ {
proxy_pass http://api_v2_backend/$1;
}
location /static {
root /var/www;
expires 30d;
}
location / {
proxy_pass http://main_backend;
}
}
Debug logda hangi location’ın seçildiğini görmek için:
grep "test location|using location|rewrite" /var/log/nginx/location_debug.log
Örnek debug çıktısı:
[debug] worker process: test location: "/api/v2/users"
[debug] worker process: test location: ~ "^/api/v2/(.*)$"
[debug] worker process: using configuration "^/api/v2/(.*)$"
Bu çıktı sana hangi location’ın kazandığını net olarak gösterir.
Gerçek Dünya Senaryosu 3: SSL/TLS Handshake Hataları
SSL sorunları debug modda inanılmaz derecede detaylı görünür. Özellikle client certificate doğrulama (mTLS) sorunlarında bu bilgiler hayat kurtarır:
server {
listen 443 ssl;
server_name secure.example.com;
error_log /var/log/nginx/ssl_debug.log debug;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_client_certificate /etc/nginx/ssl/ca.pem;
ssl_verify_client on;
location / {
proxy_pass http://backend;
}
}
SSL debug mesajlarını filtrelemek için:
# SSL handshake adımlarını takip et
grep "ssl|SSL" /var/log/nginx/ssl_debug.log | head -50
# Sertifika doğrulama hatalarını bul
grep "verify|certificate" /var/log/nginx/ssl_debug.log
# Cipher suite müzakerelerini gör
grep "cipher|protocol" /var/log/nginx/ssl_debug.log
Debug Log Dosyasını Yönetmek
Debug modu açıkken log dosyası hızla büyür. Birkaç pratik önlem almanı öneririm:
Log rotation ayarı:
# /etc/logrotate.d/nginx-debug dosyası oluştur
cat > /etc/logrotate.d/nginx-debug << 'EOF'
/var/log/nginx/*_debug.log {
daily
missingok
rotate 3
compress
delaycompress
notifempty
sharedscripts
postrotate
/bin/kill -USR1 `cat /var/run/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}
EOF
Geçici debug için log boyutunu izle:
# Debug loglamayı açtıktan sonra boyutu izle
watch -n 5 'ls -lh /var/log/nginx/debug.log && tail -1 /var/log/nginx/debug.log'
Log dosyasını sıfırla ama silme (rotation olmadan):
# Dosyayı truncate et, nginx inode'u tuttuğu için sorunsuz çalışır
> /var/log/nginx/debug.log
# Sonra nginx'e log dosyasını yeniden açmasını söyle
nginx -s reopen
Debug Log Analiz Araçları
Ham debug logu çok gürültülü olabilir. Anlamlı bilgileri çıkarmak için bazı pratik grep komutları:
# Belirli bir istek ID'sini takip et (connection numarası ile)
CONNECTION_ID="12345"
grep "*${CONNECTION_ID}" /var/log/nginx/debug.log
# Tüm benzersiz hata mesajlarını listele
grep "[error]|[warn]" /var/log/nginx/debug.log |
sed 's/[0-9]{4}/[0-9]{2}/[0-9]{2}.*] //' |
sort | uniq -c | sort -rn | head -20
# Belirli bir URL path'i için debug akışını gör
grep "GET /api/users" /var/log/nginx/debug.log |
awk '{print $NF}' | sort | uniq
# Upstream response time dağılımı
grep "upstream response time" /var/log/nginx/access.log |
awk '{print $NF}' | sort -n |
awk 'BEGIN{c=0; s=0} {c++; s+=$1; a[c]=$1} END{
print "Count:", c
print "Avg:", s/c
print "P95:", a[int(c*0.95)]
print "Max:", a[c]
}'
Nginx Debug Log ile İlgili Yaygın Yanılgılar
Yanılgı 1: “Debug log açtım ama hiçbir şey göremiyorum”
Bu genellikle iki sebepten olur. Birincisi, binary --with-debug olmadan derlenmiştir. İkincisi, error_log direktifini yanlış context’te tanımlamışsındır. debug_connection her zaman events bloğunda olmalı:
# YANLIŞ - events dışında
http {
debug_connection 192.168.1.1; # Bu çalışmaz!
}
# DOĞRU
events {
debug_connection 192.168.1.1;
}
Yanılgı 2: “Server bloğundaki error_log global olanı override eder”
Bu kısmen doğru. Server bloğundaki error_log o server için ayrı bir log dosyası açar ama global log tamamen kapanmaz. Her iki dosyaya da yazılır.
Yanılgı 3: “Debug modu performance’ı biraz etkiler”
Hayır, “biraz” değil. Debug modu ciddi şekilde etkiler. Her bağlantı için onlarca, bazen yüzlerce satır log yazılır. Yüksek trafikli ortamda disk I/O bottleneck’i yaratabilir. Asla production’da genel debug loglamayı açık bırakma. debug_connection ile sadece test IP’ni hedefle.
Config Değişikliği Sonrası Reload
Config’i güncelledikten sonra Nginx’i reload et. Restart gerektirmez:
# Config syntax kontrolü
nginx -t
# Config doğruysa reload
nginx -s reload
# veya
systemctl reload nginx
# Debug loglanmaya başladı mı kontrol et
tail -f /var/log/nginx/error.log
Debug Modunu Programatik Olarak Aç/Kapat
Bazen anlık sorun yakalama için debug modunu dinamik olarak açıp kapatman gerekebilir. Bunun için basit bir script işe yarar:
#!/bin/bash
# /usr/local/bin/nginx-debug-toggle
NGINX_CONF="/etc/nginx/nginx.conf"
BACKUP_CONF="/etc/nginx/nginx.conf.backup"
toggle_debug() {
local action=$1
cp $NGINX_CONF $BACKUP_CONF
if [ "$action" = "on" ]; then
sed -i 's/error_log.*error;/error_log /var/log/nginx/error.log debug;/' $NGINX_CONF
echo "Debug mode: ON"
elif [ "$action" = "off" ]; then
sed -i 's/error_log.*debug;/error_log /var/log/nginx/error.log warn;/' $NGINX_CONF
echo "Debug mode: OFF"
fi
nginx -t && nginx -s reload || {
echo "Config hatasi, geri yukleniyor..."
cp $BACKUP_CONF $NGINX_CONF
nginx -s reload
}
}
case "$1" in
on|off) toggle_debug $1 ;;
*) echo "Kullanim: $0 [on|off]" ;;
esac
chmod +x /usr/local/bin/nginx-debug-toggle
# Debug'ı aç
nginx-debug-toggle on
# Sorunu repro et, logları incele
tail -f /var/log/nginx/error.log
# Debug'ı kapat
nginx-debug-toggle off
Sonuç
Nginx debug loglama, sysadmin hayatını kurtaran ama dikkatli kullanılması gereken güçlü bir araç. Özetlemek gerekirse:
--with-debugflag olmadan binary debug log üretmez, önce bunu kontrol et- Production’da global debug yerine mutlaka
debug_connectionile spesifik IP hedefle - Virtual host bazlı debug logları izolasyon ve analiz kolaylığı sağlar
- Log dosyası büyümesini izle, gerektiğinde truncate et veya rotation kur
- Upstream sorunları, location eşleşme problemleri ve SSL handshake hataları için debug log birinci tercih olmalı
- İşin bitince debug modunu kapat, reload etmeyi unutma
Debug log sana Nginx’in iç dünyasını adım adım gösterir. Saatlerce sürebilecek bir sorun tespiti, doğru filtreleme komutlarıyla birkaç dakikaya inebilir. Önemli olan log gürültüsüne boğulmamak ve neye baktığını bilmek.
