Apache Hata Mesajlarını Okuma ve Yorumlama

Bir sunucuyu yönetirken en bunaltıcı anlardan biri, kullanıcılardan “site çalışmıyor” mesajı almak ve ekrana boş boş bakmaktır. Apache hata mesajları tam da bu noktada senin en iyi arkadaşın olur, tabii onları doğru okumayı bilirsen. Yıllar içinde fark ettim ki pek çok sysadmin log dosyalarına bakar ama gerçekten okumaz. Bu yazıda Apache hata mesajlarını sadece görmekle kalmayıp anlamayı, yorumlamayı ve harekete geçmeyi konuşacağız.

Apache Log Dosyaları Nerede Bulunur?

Önce temel bilgiyle başlayalım. Apache’nin log dosyaları dağıtıma göre farklı yerlerde oturur.

Debian/Ubuntu tabanlı sistemlerde:

  • /var/log/apache2/error.log – Hata logları
  • /var/log/apache2/access.log – Erişim logları

RHEL/CentOS/AlmaLinux tabanlı sistemlerde:

  • /var/log/httpd/error_log
  • /var/log/httpd/access_log

Virtual host bazlı özel log tanımı:

# /etc/apache2/sites-available/ornek.com.conf içinde
ErrorLog ${APACHE_LOG_DIR}/ornek.com-error.log
CustomLog ${APACHE_LOG_DIR}/ornek.com-access.log combined

Hangi sanal host’un hangi log dosyasını kullandığını bulmak için şu komutu kullanabilirsin:

grep -r "ErrorLog" /etc/apache2/sites-enabled/

Bu komut sana tüm aktif sanal host’ların hata log dosyalarını listeler. Acil bir durumda nereye bakacağını bilmek zaman kazandırır.

Hata Mesajı Anatomisi

Apache hata log satırlarını ilk gördüğünde karmaşık görünebilir. Ama aslında her satır belirli bir format izler:

[Pzt Oca 15 14:23:07.123456 2024] [ssl:warn] [pid 12345] AH01906: ornek.com:443:0 server certificate is a CA certificate (BasicConstraints: CA == TRUE !?)

Bu satırı parçalara ayıralım:

  • [Pzt Oca 15 14:23:07.123456 2024]: Timestamp, mikrosaniye hassasiyetinde
  • [ssl:warn]: Modül adı ve hata seviyesi
  • [pid 12345]: Hatayı üreten Apache worker process’in ID’si
  • AH01906: Apache’nin kendi hata kodu (AH = Apache HTTPD)
  • Geri kalan kısım: İnsan tarafından okunabilir hata açıklaması

Bu yapıyı anlamak, büyük log dosyalarında grep ile arama yaparken işini kolaylaştırır.

Log Seviyeleri ve Anlamları

Apache sekiz farklı log seviyesi kullanır. Bunları bilmek, neye dikkat edip neyi görmezden geleceğini anlamana yardımcı olur.

  • emerg: Sistem kullanılamaz durumda, Apache ayağa kalkamıyor
  • alert: Hemen müdahale gerekiyor
  • crit: Kritik durum, örneğin disk doldu
  • error: Hata oluştu ama sistem çalışmaya devam ediyor
  • warn: Uyarı, bir şeyler yanlış ama henüz sorun yok
  • notice: Normal ama önemli bir durum
  • info: Bilgilendirme amaçlı
  • debug: Geliştirici için detaylı bilgi

Üretim ortamında genellikle warn veya error seviyesini kullanırsın. debug sadece sorun giderme sırasında açılır çünkü disk doldurmak için mükemmeldir.

Log seviyesini değiştirmek için:

# apache2.conf veya httpd.conf içinde
LogLevel warn

# Sadece belirli bir modül için debug açmak
LogLevel warn ssl:info rewrite:trace3

En Sık Karşılaşılan Hata Kodları ve Çözümleri

403 Forbidden Hataları

Üretimde en çok başım ağrıyan hatalardan biri 403’tür. Log’da genellikle şöyle görünür:

[error] [client 192.168.1.100] AH01630: client denied by server configuration: /var/www/html/gizli-dizin

veya:

[error] [client 192.168.1.100] AH00035: access to /var/www/html/index.php denied (filesystem path '/var/www/html/index.php') because search permissions are missing on a component of the path

İkinci mesaj çok önemli. “search permissions missing” dediğinde dosya izni değil dizin izni sorunudur. Apache’nin dizin üzerinden geçmesi için execute (x) iznine ihtiyacı var.

# Sorunlu dosyanın tüm üst dizinlerini kontrol et
namei -l /var/www/html/index.php

# Tipik düzeltme
chmod 755 /var/www/html
chmod 644 /var/www/html/index.php

# SELinux varsa (RHEL sistemlerde)
ls -laZ /var/www/html/
restorecon -Rv /var/www/html/

500 Internal Server Error

Bu hata en sinir bozucu olanı çünkü kullanıcı hiçbir şey görmez, sen de log’a koşarsın:

[error] [pid 23456] [client 10.0.0.5:52341] AH01215: /var/www/html/uygulama/.htaccess: Invalid command 'Options', perhaps misspelled or defined by a module not included in the server configuration

Bu mesaj .htaccess dosyasında bir direktifin yüklenmeyen bir modüle ihtiyaç duyduğunu söylüyor. Çözüm:

# Hangi modüllerin yüklü olduğunu gör
apache2ctl -M | grep -i rewrite

# Modülü etkinleştir
a2enmod rewrite

# Konfigürasyonu test et
apache2ctl configtest

# Yeniden başlat
systemctl reload apache2

PHP uygulamalarında 500 hatası sıklıkla PHP’nin kendi hata loguna düşer, Apache log’una değil. Bu nedenle:

# PHP-FPM log kontrolü
tail -f /var/log/php8.1-fpm.log

# PHP hata logunu Apache ile birleştirme
# php.ini'de:
# error_log = /var/log/apache2/php-errors.log

AH00558 Uyarısı

Yeni kurulan sistemlerde sık görülür:

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message

Tehlikeli bir hata değil ama log’u kirletiyor. Düzeltmesi basit:

echo "ServerName localhost" >> /etc/apache2/apache2.conf
apache2ctl configtest && systemctl reload apache2

Gerçek Dünya Senaryosu: SSL Sertifika Sorunu

Geçen ay yaşadığım bir olayı paylaşayım. Saat 02:00’de telefon çaldı, e-ticaret sitesi erişilemez. Log’a baktım:

[Mon Jan 15 02:15:33.442891 2024] [ssl:emerg] [pid 98765] AH02565: Certificate and private key ornek.com:443:0 from /etc/ssl/certs/ornek.com.crt and /etc/ssl/private/ornek.com.key do not match
[Mon Jan 15 02:15:33.443012 2024] [ssl:emerg] [pid 98765] SSL Library Error: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch

Mesaj net: Sertifika ve private key eşleşmiyor. Bu genellikle sertifika yenilenirken yanlış key ile eşleştirildiğinde olur.

# Sertifika ve key'in eşleşip eşleşmediğini doğrula
openssl x509 -noout -modulus -in /etc/ssl/certs/ornek.com.crt | md5sum
openssl rsa -noout -modulus -in /etc/ssl/private/ornek.com.key | md5sum

# İkisi aynı hash'i vermiyorsa key yanlış
# Doğru key'i bul
find /etc/ssl/ -name "*.key" -exec sh -c 'echo "=== {} ===" && openssl rsa -noout -modulus -in {} 2>/dev/null | md5sum' ;

Hash’ler eşleşince doğru key’i yerine koydum ve servisi ayağa kaldırdım. Tüm süreç 8 dakika sürdü. Log mesajını anlamamış olsaydım saatlerce sürebilirdi.

Log Analizi için Vazgeçilmez Araçlar

tail ve grep Kombinasyonu

Canlı log takibi için en temel araç:

# Gerçek zamanlı hata takibi
tail -f /var/log/apache2/error.log

# Sadece error seviyesindeki mesajları göster
tail -f /var/log/apache2/error.log | grep "[error]"

# Belirli bir IP'den gelen hataları filtrele
tail -f /var/log/apache2/error.log | grep "192.168.1.100"

# Son 1 saat içindeki kritik hataları say
grep "$(date -d '1 hour ago' +'%b %d %H')" /var/log/apache2/error.log | grep -c "[error]"

Apache’nin Kendi Durum Sayfası

mod_status aktifse altın değerinde bilgi verir:

# mod_status'u etkinleştir (zaten etkin değilse)
a2enmod status

# /etc/apache2/mods-enabled/status.conf içine ekle
# Sadece localhost erişimi için
<Location /server-status>
    SetHandler server-status
    Require ip 127.0.0.1
</Location>

# Komut satırından kontrol
curl http://localhost/server-status?auto

apachectl ile Anlık Tanı

# Konfigürasyon sözdizimini kontrol et
apachectl configtest

# Yüklü modülleri listele
apachectl -M

# Apache'nin gördüğü tüm konfigürasyonu dump et
apachectl -S

# Sanal host yapılandırmasını göster
apachectl -S 2>&1 | grep -A 5 "ornek.com"

.htaccess Hatalarını Okuma

.htaccess dosyaları hata kaynağı olmaya bayılır. Özellikle paylaşımlı hosting ortamından taşınan siteler. Log’da şöyle görünür:

[error] [pid 11111] [client 85.100.200.50:34521] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

Bu mesaj sonsuz yönlendirme döngüsü olduğunu söylüyor. Genellikle kötü yazılmış RewriteRule’dan kaynaklanır:

# Sorunu debug modda incele
# VirtualHost bloğuna ekle:
LogLevel alert rewrite:trace3

# Sonra log'u filtrele
tail -f /var/log/apache2/error.log | grep "rewrite"

Trace log’unda şöyle bir şey görürsün:

[rewrite:trace3] [pid 11112] mod_rewrite.c(476): [client 85.100.200.50] applying pattern '^(.*)$' to uri '/index.php'
[rewrite:trace3] [pid 11112] mod_rewrite.c(476): [client 85.100.200.50] applying pattern '^(.*)$' to uri '/index.php'

Aynı URI tekrar tekrar eşleşiyorsa koşul eksik demektir. Düzeltme:

# Sorunlu kural
RewriteRule ^(.*)$ /index.php?q=$1 [L]

# Doğrusu - döngüyü önle
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?q=$1 [L]

Yoğun Trafik Altında Hata Analizi

Bir gün aniden artan 503 hatalarıyla karşılaştım. Log doluydu:

[error] [pid 45678] (111)Connection refused: AH00957: HTTP: attempt to connect to 127.0.0.1:9000 (localhost) failed
[error] [pid 45679] [client 78.190.100.200:41233] AH01079: failed to make connection to backend: localhost

Bu mesajlar Apache’nin PHP-FPM’e bağlanamadığını gösteriyor. Port 9000’e bağlantı reddediliyor.

# PHP-FPM çalışıyor mu?
systemctl status php8.1-fpm

# Socket veya port dinleniyor mu?
ss -tlnp | grep 9000
# veya unix socket kullanıyorsa
ls -la /run/php/php8.1-fpm.sock

# PHP-FPM worker sayısını kontrol et
# /etc/php/8.1/fpm/pool.d/www.conf içinde
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35

# Anlık durum
curl http://localhost/fpm-status 2>/dev/null || 
  php-fpm8.1 -t

Bu senaryoda PHP-FPM max_children limitine ulaşmıştı. Tüm worker’lar meşguldü ve yeni bağlantılar reddediliyordu. pm.max_children değerini artırmak çözüm oldu.

Log Rotasyonu Sorunları

Bazen log dosyasının rotasyon sonrası yazılamaz hale geldiğini görürsün:

[alert] [pid 1] (13)Permission denied: AH00052: child process 34567 said into stderr: (13)Permission denied: AH02455: Could not open error log file /var/log/apache2/error.log.
# Log dosyasının sahibini ve izinlerini kontrol et
ls -la /var/log/apache2/

# Doğru izinler
chown root:adm /var/log/apache2/error.log
chmod 640 /var/log/apache2/error.log

# logrotate konfigürasyonunu kontrol et
cat /etc/logrotate.d/apache2

# Rotasyonu manuel test et
logrotate -d /etc/logrotate.d/apache2

# Apache'ye yeni log dosyasını açmasını söyle
systemctl reload apache2
# veya
kill -USR1 $(cat /var/run/apache2/apache2.pid)

Hata Mesajlarını Sistematik Okuma Yaklaşımı

Yıllar içinde geliştirdiğim bir yaklaşım var. Bir hata mesajıyla karşılaştığında şu sırayı izle:

İlk olarak zaman damgasına bak. Hata ne zaman başladı? Bir deployment, cron job veya sistem değişikliğiyle örtüşüyor mu?

İkinci olarak hata seviyesine bak. emerg ve crit varsa önce servisi ayağa kaldır, sonra araştır. error ise metodlu ilerle.

Üçüncü olarak modül adına bak. [ssl:error] farklı bir yere bakmayı, [rewrite:error] farklı bir yere bakmayı gerektirir.

Dördüncü olarak AH kodunu araştır. Apache’nin resmi hata kodları kataloğu çok değerlidir: https://error.apache.org/

Beşinci olarak client IP’sine bak. Hata tek bir IP’den mi geliyor yoksa herkese mi etkiliyor? Bu sorunun kapsamını belirler.

# Son 24 saatin hata özetini çıkar
awk '{print $8}' /var/log/apache2/error.log | sort | uniq -c | sort -rn | head -20

# En çok hata alan IP'leri bul
grep "client" /var/log/apache2/error.log | grep -oP 'client K[0-9.]+' | sort | uniq -c | sort -rn | head -10

# Belirli bir zaman aralığındaki hataları filtrele
awk '/Jan 15 14:00/,/Jan 15 15:00/' /var/log/apache2/error.log | grep "[error]" | wc -l

Proaktif İzleme Kurulumu

Hataları gerçek zamanlı yakalamak için basit bir script işe yarıyor:

#!/bin/bash
# /usr/local/bin/apache-hata-izle.sh

LOG_DOSYASI="/var/log/apache2/error.log"
ESIK=10
EMAIL="[email protected]"
KONTROL_SURESI=300 # 5 dakika

HATA_SAYISI=$(tail -n 1000 "$LOG_DOSYASI" | 
  awk -v since="$(date -d '5 minutes ago' +'%b %d %H:%M')" 
  '$0 >= since' | grep -c "[error]")

if [ "$HATA_SAYISI" -gt "$ESIK" ]; then
    echo "UYARI: Son 5 dakikada $HATA_SAYISI Apache hatası!" | 
    mail -s "Apache Hata Alarmı - $(hostname)" "$EMAIL"
fi
# Crontab'a ekle
*/5 * * * * /usr/local/bin/apache-hata-izle.sh

Sonuç

Apache hata mesajları bir sistemi anlamanın en kısa yolu. Her satır sana bir hikaye anlatıyor; kim bağlandı, ne istedi, neden başarısız oldu ve hangi bileşen devreye girdi. Bu hikayeyi okumayı öğrendikçe sorun çözme sürenin dramatik biçimde düştüğünü göreceksin.

Pratik önerim şu: Acil bir şey olmasa bile haftada bir saatini log dosyalarını incelemeye harca. Uyarı seviyesindeki mesajlar bugün sorun değil ama yarın kriz olabilir. Sertifika süresi dolmadan önce ssl:warn log’u seni uyarıyor, max_children limitine yaklaşmadan önce PHP-FPM pool dolu mesajları geliyor.

Son olarak şunu söyleyeyim: Bir hata mesajını anlayamadığında Google’a kopyala yapıştır yapmadan önce mesajı parçalara ayır. Modül adına bak, AH koduna bak, apache.error.org’a bak. Çoğu zaman dokümantasyonun kendisi seni doğrudan çözüme götürür. Log okuma bir beceri ve her beceri gibi pratikle gelişir.

Benzer Konular

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir