Apache 500 Internal Server Error Hatası Nasıl Çözülür?
Gece yarısı telefonun çalıyor, izleme sisteminiz alarm veriyor ve kullanıcılar sitenin “500 Internal Server Error” verdiğini bildiriyor. Bu senaryo her sysadmin’in korkulu rüyasıdır. Paniklemeden, sistematik bir yaklaşımla bu hatayı çözmek hem mümkün hem de düşündüğünüzden çok daha hızlı yapılabilir. Bu yazıda Apache üzerinde 500 hatasını nasıl adım adım tespit edip çözeceğinizi gerçek dünya senaryolarıyla anlatacağım.
500 Internal Server Error Nedir ve Neden Olur?
500 hatası, Apache’nin isteği işlerken beklenmedik bir sorunla karşılaştığını ve ne yapacağını bilemediğini söylemesinin kibarca yoludur. Sunucu taraflı bir hata olduğu için kullanıcıya neredeyse hiçbir bilgi verilmez, tüm detaylar log dosyalarındadır.
En sık karşılaşılan nedenler şunlardır:
- .htaccess dosyasındaki hatalar: Yanlış yazılmış rewrite kuralları veya desteklenmeyen direktifler
- PHP hataları: Fatal error, syntax hatası veya bellek sınırı aşımı
- Dosya izin sorunları: Yanlış chmod/chown ayarları
- CGI/Script hataları: Çalıştırılabilir betiklerdeki sorunlar
- Modül uyumsuzlukları: Etkin olmayan veya çakışan Apache modülleri
- Kaynak tükenmesi: Bellek, işlem sayısı veya bağlantı limitleri
İlk Adım: Log Dosyalarına Bakın
Her şeyden önce logları kontrol etmelisiniz. Apache’nin error log dosyası her şeyi bilir.
# Varsayılan error log konumları
tail -f /var/log/apache2/error.log # Debian/Ubuntu
tail -f /var/log/httpd/error_log # CentOS/RHEL
tail -f /var/log/apache2/error.log -n 100 # Son 100 satır
# Virtual host'a özel error log
tail -f /var/www/sitem.com/logs/error.log
# Sadece 500 hatalarını filtrele
grep "500" /var/log/apache2/access.log | tail -20
# Hata mesajlarını zaman damgasıyla filtrele
grep "$(date '+%a %b %d')" /var/log/apache2/error.log | grep -i "error"
Bir log satırı tipik olarak şöyle görünür:
[Fri Nov 10 02:15:33.456789 2023] [php7:error] [pid 12345] [client 192.168.1.100:54321] PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/html/app/model.php on line 234
Bu çıktıdan şunları anlıyoruz: hangi modülün hata verdiğini, hangi IP’den geldiğini, hatanın tam açıklamasını ve hangi dosyanın kaçıncı satırında olduğunu. Log okumayı öğrenmek, sorun çözme sürenizi yarıya indirir.
.htaccess Kaynaklı 500 Hataları
Deneyimlerime göre 500 hatalarının büyük çoğunluğu .htaccess dosyasından kaynaklanır. Özellikle WordPress, Laravel gibi framework’lerde bu çok sık görülür.
# .htaccess'i geçici olarak devre dışı bırak
mv /var/www/html/.htaccess /var/www/html/.htaccess.bak
# Siteyi test et, hata gidiyorsa sorun .htaccess'tedir
curl -I https://siteadresi.com
# Apache konfigürasyonunu sözdizimi açısından kontrol et
apachectl configtest
apache2ctl configtest
# .htaccess syntax hatası için Apache logunu izle
tail -f /var/log/apache2/error.log &
curl -s https://siteadresi.com > /dev/null
En sık görülen .htaccess hataları şunlardır:
- mod_rewrite aktif değil:
RewriteEngine Onsatırı hata veriyor - Yanlış RewriteBase: Subdirectory kurulumlarında eksik veya hatalı path
- Desteklenmeyen direktif: Sunucuya özgü direktifler başka sunucuda çalışmıyor
- Sonsuz döngü: Yanlış yazılmış rewrite kuralları
mod_rewrite aktif değilse şu komutla etkinleştirin:
# mod_rewrite etkinleştir (Debian/Ubuntu)
a2enmod rewrite
systemctl restart apache2
# Gerekli AllowOverride ayarını kontrol et
grep -r "AllowOverride" /etc/apache2/
# veya
grep -r "AllowOverride" /etc/httpd/
# AllowOverride All yapılandırması örneği
cat /etc/apache2/sites-available/000-default.conf
Virtual host konfigürasyonunuzda şu bloğun olduğundan emin olun:
# Virtual host konfigürasyonunu düzenle
nano /etc/apache2/sites-available/sitem.com.conf
# İçinde şu bölüm olmalı:
# <Directory /var/www/html>
# AllowOverride All
# Options Indexes FollowSymLinks
# Require all granted
# </Directory>
PHP Fatal Error ve Script Hataları
PHP hataları da 500’ün çok yaygın nedenidir. PHP’nin hata gösterimi production’da kapalıysa, hatayı sadece logdan görebilirsiniz.
# PHP hata logunu kontrol et
tail -f /var/log/php_errors.log
tail -f /var/log/apache2/error.log | grep -i "php"
# PHP'nin mevcut ayarlarını kontrol et
php -i | grep -E "error_reporting|display_errors|log_errors|error_log"
# Komut satırından PHP script'ini test et
php -l /var/www/html/index.php # Syntax kontrolü
php /var/www/html/problem_dosya.php # Direkt çalıştır
# PHP bellek limitini kontrol et
php -i | grep memory_limit
Geliştirme ortamında hata görüntülemeyi açmak için:
# php.ini'yi düzenle (dikkat: production'da kapalı tutun!)
nano /etc/php/8.1/apache2/php.ini
# Veya geçici test için .htaccess'e ekle:
# php_flag display_errors on
# php_value error_reporting E_ALL
# php.ini konumunu bul
php --ini
php -i | grep "Loaded Configuration File"
# Değişiklik sonrası Apache'yi yeniden başlat
systemctl restart apache2
Gerçek dünya senaryosu: Bir e-ticaret sitesinde büyük ürün kataloğu yüklenirken hafıza tükenmesi yaşanıyordu. Log dosyasında PHP Fatal error: Allowed memory size exhausted görüyorduk. Çözüm basitti:
# php.ini veya .htaccess'te memory limit artır
# php.ini:
# memory_limit = 256M
# .htaccess:
# php_value memory_limit 256M
# Veya script içinde geçici olarak:
# ini_set('memory_limit', '256M');
# Değişikliği doğrula
php -i | grep memory_limit
curl -I https://siteadresi.com
Dosya İzin Sorunları
Bu konuda çok acı tecrübelerim var. Bir sunucu taşıma işleminin ardından tüm site 500 hata vermeye başlamıştı. Neden? rsync ile kopyalamada izinler bozulmuştu.
# Dosya izinlerini kontrol et
ls -la /var/www/html/
stat /var/www/html/index.php
# Web server kullanıcısını öğren
ps aux | grep apache
ps aux | grep httpd
# Genellikle www-data (Ubuntu) veya apache (CentOS)
# Tipik doğru izin yapısı
find /var/www/html -type f -exec chmod 644 {} ;
find /var/www/html -type d -exec chmod 755 {} ;
# Sahipliği düzelt
chown -R www-data:www-data /var/www/html/ # Ubuntu/Debian
chown -R apache:apache /var/www/html/ # CentOS/RHEL
# Yazılabilir dizinler için (uploads, cache, tmp)
chmod 775 /var/www/html/wp-content/uploads
chmod 775 /var/www/html/storage
# SELinux bağlamını kontrol et (CentOS/RHEL)
ls -Z /var/www/html/
restorecon -Rv /var/www/html/
Önemli not: 777 izin vermeyin. Bu hem güvenlik açığı hem de bazı durumlarda PHP güvenlik ayarları nedeniyle 500 hatasına neden olabilir. Özellikle open_basedir ve safe_mode aktifse.
CGI Script Hataları
CGI scriptleri çalıştırıyorsanız (Perl, Python, Bash tabanlı), bunlara özgü sorunlar yaşayabilirsiniz.
# CGI script'i komut satırından test et
/var/www/cgi-bin/myscript.pl
/var/www/cgi-bin/myscript.py
# Gerekli header çıktısı olmalı, örnek:
# Content-Type: text/html
# (boş satır)
# HTML içerik
# CGI script izinlerini kontrol et
ls -la /var/www/cgi-bin/
chmod 755 /var/www/cgi-bin/myscript.pl
# Shebang satırını kontrol et
head -1 /var/www/cgi-bin/myscript.pl
# #!/usr/bin/perl olmalı
# Perl yolunu bul
which perl
which python3
# Satır sonu karakteri sorunu (Windows'tan gelmiş dosya)
file /var/www/cgi-bin/myscript.pl
dos2unix /var/www/cgi-bin/myscript.pl
Apache Konfigürasyon Hataları
Konfigürasyon dosyalarındaki hatalar da 500’e yol açabilir veya Apache’nin hiç başlamamasına neden olabilir.
# Konfigürasyon sözdizimini kontrol et
apachectl -t
apache2ctl configtest
# Detaylı konfigürasyon çıktısı
apachectl -S # Virtual host bilgileri
apache2ctl -D DUMP_RUN_CFG
# Aktif modülleri listele
apache2ctl -M
apachectl -M | grep -i rewrite
# Konfigürasyon dosyalarını tara
grep -r "ServerName" /etc/apache2/sites-enabled/
grep -rn "SSLCertificateFile" /etc/apache2/
# Include edilen dosyaları bul
apache2ctl -t -D DUMP_INCLUDES
# Konfigürasyon değişikliği sonrası graceful restart (bağlantıları kesmez)
apachectl graceful
systemctl reload apache2
Gerçek senaryo: Bir virtual host konfigürasyonuna yanlışlıkla fazladan etiketi eklenmişti. apachectl configtest anında hatayı gösterdi:
Syntax error on line 45 of /etc/apache2/sites-enabled/sitem.com.conf:
</VirtualHost> without matching <VirtualHost>
Bu tür hataları elle aramak yerine configtest ile yakalamak çok daha hızlıdır.
Gerçek Dünya Debug Senaryosu: Adım Adım İnceleme
Bir arkadaşımın yönettiği haber sitesi aniden 500 vermeye başladı. İşte tam debug süreci:
# 1. Adım: Log'a bak
tail -50 /var/log/apache2/error.log
# Çıktı:
# [error] [pid 8921] [client 85.105.x.x] FastCGI: incomplete headers (0 bytes) received from server "/var/www/haber/index.php"
# 2. Adım: PHP-FPM durumunu kontrol et
systemctl status php8.1-fpm
journalctl -u php8.1-fpm -n 50
# PHP-FPM log
tail -f /var/log/php8.1-fpm.log
# 3. Adım: PHP-FPM process sayısını kontrol et
ps aux | grep php-fpm | wc -l
# 4. Adım: Sistem kaynaklarını kontrol et
free -m
df -h
top -bn1 | head -20
# 5. Adım: PHP-FPM pool konfigürasyonunu kontrol et
cat /etc/php/8.1/fpm/pool.d/www.conf | grep -E "pm.|max_children"
Sorun neydi? PHP-FPM max_children değeri 5 olarak ayarlıydı ve yoğun trafik anında tüm worker’lar dolmuştu. Çözüm:
# PHP-FPM pool ayarını düzenle
nano /etc/php/8.1/fpm/pool.d/www.conf
# Şu değerleri sunucuya göre ayarla:
# pm = dynamic
# pm.max_children = 50
# pm.start_servers = 10
# pm.min_spare_servers = 5
# pm.max_spare_servers = 20
# Yeniden başlat
systemctl restart php8.1-fpm
systemctl restart apache2
# Gerçek zamanlı izleme
watch -n 1 'ps aux | grep php-fpm | grep -v grep | wc -l'
Strace ile Derinlemesine Analiz
Loglar yeterli bilgi vermiyorsa, strace ile Apache process’ini izleyebilirsiniz. Bu biraz ileri seviye ama çok güçlü bir araçtır.
# Apache worker PID'ini bul
ps aux | grep apache2 | grep -v grep | head -5
# Strace ile takip et
strace -p 12345 -e trace=file 2>&1 | head -50
# Daha okunabilir çıktı için
strace -p 12345 -f -e trace=openat,read,write 2>&1 | grep -i error
# Hangi dosyalara erişilmeye çalışılıyor
strace -p 12345 -e trace=openat 2>&1 | grep "ENOENT|EACCES"
Bu yöntemle “dosya bulunamadı” veya “erişim reddedildi” hatalarını Apache loguna yansımadan yakalayabilirsiniz.
Önleyici Tedbirler ve İzleme
Yangın çıktıktan sonra söndürmek yerine önlemek daha akıllıca. İşte birkaç pratik öneri:
# Apache durumunu sürekli izle
# mod_status etkinleştir
a2enmod status
nano /etc/apache2/conf-available/server-status.conf
# İçeriği:
# <Location /server-status>
# SetHandler server-status
# Require ip 127.0.0.1
# </Location>
a2enconf server-status
systemctl reload apache2
# Status'u kontrol et
curl http://localhost/server-status?auto
# Logrotate ayarlarını kontrol et (loglar dolmasin)
cat /etc/logrotate.d/apache2
# Disk doluluk alarmı için basit script
df -h / | awk 'NR==2 {if($5+0 > 85) print "UYARI: Disk %"$5" dolu!"}'
# 500 hata sayısını izle
grep " 500 " /var/log/apache2/access.log | wc -l
Ayrıca şu araçları kullanmanızı tavsiye ederim:
- GoAccess: Gerçek zamanlı log analizi için mükemmel, terminal tabanlı
- Fail2ban: Tekrarlayan hatalı istekleri engeller
- Logwatch: Günlük log özeti e-postası gönderir
- Munin/Nagios: Apache metriklerini zaman içinde izler
Hızlı Kontrol Listesi
500 hatası aldığınızda şu sırayı takip edin:
- Error log’u kontrol et:
tail -100 /var/log/apache2/error.log - .htaccess’i geçici kaldır:
mv .htaccess .htaccess.bakile test et - Konfigürasyonu doğrula:
apachectl configtest - Dosya izinlerini kontrol et:
ls -lavestatkomutları - PHP logunu incele:
tail -f /var/log/php_errors.log - Disk alanını kontrol et:
df -hile dolu disk mi? - Bellek durumunu gör:
free -mile RAM tükenmesi var mı? - Apache’yi yeniden başlat: Değişiklik yaptıktan sonra mutlaka
- Tarayıcı cache’ini temizle: Bazen sorun orada
Sonuç
500 Internal Server Error, göründüğü kadar korkutucu değil. Sistematik bir yaklaşımla, genellikle 5-10 dakika içinde sorunu tespit edip çözebilirsiniz. Kritik nokta şudur: her zaman logdan başlayın. Apache size her şeyi söyler, sadece dinlemeyi bilmek gerekir.
En önemli alışkanlık, production ortamında değişiklik yapmadan önce apachectl configtest çalıştırmak ve log dosyalarını aktif tutmaktır. Loglar olmadan karanlıkta el yordamıyla iş yapıyorsunuz demektir.
Bir de şunu söyleyeyim: bu tür hataları çözdükçe bir sonrakinde çok daha hızlı oluyorsunuz. Her 500 hatası, sisteminizi daha iyi tanımanızı sağlayan bir öğrenme fırsatıdır. Gece yarısı alarmlarına hazırlıklı olmak için bu debug adımlarını alışkanlık haline getirin, kendinize bir runbook oluşturun ve takımınızla paylaşın.
