IIS 500 Hatası: Web Sunucusunda Hata Ayıklama Rehberi

Bir web sunucusunda IIS 500 hatası almak, özellikle production ortamında can sıkıcı bir durum. Kullanıcılar sayfaya erişemiyor, telefon çalmaya başlıyor ve sen ekranın karşısında “Internal Server Error” yazısına bakıyorsun. Ama şunu söyleyeyim: IIS 500 hataları, doğru araçları kullandığında genellikle çok hızlı çözülüyor. Bu yazıda, IIS 500 hatalarını kök nedenine kadar iz sürerek nasıl çözeceğini adım adım anlatacağım.

IIS 500 Hatası Nedir ve Neden Olur?

HTTP 500 “Internal Server Error”, web sunucusunun isteği işlerken beklenmedik bir hatayla karşılaştığı anlamına gelir. IIS özelinde bu hata genellikle şu durumlarda ortaya çıkar:

  • Uygulama havuzu (Application Pool) çökmesi veya yanlış yapılandırması
  • ASP.NET veya ASP uygulama kodunda işlenmeyen exception
  • web.config dosyasında sözdizimi hatası veya yanlış yapılandırma
  • Yetersiz dosya/klasör izinleri
  • Eksik veya uyumsuz .NET Framework versiyonu
  • Bağlantı string hatası veya veritabanı erişim sorunu
  • CGI veya ISAPI uzantı sorunları

500 hatasının sinsi tarafı şu: Kullanıcıya sadece genel bir hata mesajı gösterirken, asıl sorun bambaşka bir yerde gizlenmiş olabilir. Bu yüzden hata ayıklama sürecini sistematik ilerletmek şart.

Adım 1: Detaylı Hata Mesajlarını Etkinleştir

IIS, varsayılan olarak güvenlik nedeniyle hata detaylarını gizler. İlk yapacağın şey detaylı hata mesajlarını açmak. Bunu hem IIS Manager üzerinden hem de web.config dosyasından yapabilirsin.

web.config üzerinden:

# web.config dosyasını aç ve system.web bölümüne ekle
notepad C:inetpubwwwrootsitenin-klasoruweb.config
<configuration>
  <system.web>
    <customErrors mode="Off" />
    <compilation debug="true" />
  </system.web>
  <system.webServer>
    <httpErrors errorMode="Detailed" existingResponse="PassThrough" />
  </system.webServer>
</configuration>

Önemli not: Bu ayarları production ortamında geçici olarak aç, hatayı bulduktan sonra mutlaka geri al. Detaylı hata mesajları stack trace ve sunucu bilgilerini dışarıya sızdırabilir.

IIS Manager üzerinden yapmak istersen: Sites > Sitenin adı > Error Pages > Edit Feature Settings > Detailed Errors seçeneğini işaretle.

Adım 2: IIS Loglarını Analiz Et

IIS logları, neyin ne zaman patladığını anlamanın en hızlı yolu. Varsayılan log konumu şu şekilde:

# IIS log dosyalarının varsayılan konumu
C:inetpublogsLogFilesW3SVC1

# Powershell ile son log dosyasını bul
Get-ChildItem "C:inetpublogsLogFiles" -Recurse | Sort-Object LastWriteTime -Descending | Select-Object -First 5

Log dosyasını açtığında şöyle satırlar göreceksin:

2024-01-15 14:32:11 192.168.1.100 GET /uygulama/giris.aspx - 80 - 10.0.0.5 Mozilla/5.0 500 0 0 1250

Buradaki kolonlar soldan sağa: tarih, saat, client IP, metod, URL path, port, kullanıcı adı, sunucu IP, user agent, HTTP durum kodu, alt durum kodu, win32 hata kodu, süre (ms).

500 hatalarını filtrele:

# Powershell ile sadece 500 hatalarını filtrele
Select-String -Path "C:inetpublogsLogFilesW3SVC1u_ex*.log" -Pattern " 500 "

# Belirli bir tarih aralığındaki 500 hatalarını say
$logPath = "C:inetpublogsLogFilesW3SVC1"
Get-ChildItem $logPath -Filter "*.log" | ForEach-Object {
    $content = Get-Content $_.FullName
    $errors = $content | Where-Object { $_ -match " 500 " }
    if ($errors) {
        Write-Host "$($_.Name): $($errors.Count) adet 500 hatasi"
    }
}

Adım 3: Windows Event Log Kontrolü

IIS logları 500 hatası gösterse de, asıl exception detayları çoğunlukla Windows Event Log’da gizlidir. Özellikle uygulama havuzu çökmelerinde burası altın madeni.

# Event Viewer'ı aç
eventvwr.msc

# Powershell ile Application log'dan son 50 hatayı çek
Get-EventLog -LogName Application -EntryType Error -Newest 50 | 
    Where-Object { $_.Source -like "*IIS*" -or $_.Source -like "*ASP*" -or $_.Source -like "*W3SVC*" } |
    Format-List TimeGenerated, Source, Message

Failed Request Tracing (FREB) aktif et:

Bence en güçlü IIS hata ayıklama aracı FREB. Başarısız istekleri detaylı olarak kaydeder ve nerede takıldığını tam olarak gösterir.

# Powershell ile Failed Request Tracing'i etkinleştir
Import-Module WebAdministration
Set-WebConfiguration system.webServer/tracing/traceFailedRequests -PSPath "IIS:SitesDefault Web Site" -Value @{
    enabled = $true
    path = "%SystemDrive%inetpublogsFailedReqLogFiles"
}

IIS Manager üzerinden: Site > Failed Request Tracing Rules > Add > All Content (*) > Status Code: 500 şeklinde kural oluştur.

FREB logları XML formatında kaydedilir ve tarayıcıda açılabilir:

C:inetpublogsFailedReqLogFilesW3SVC1fr000001.xml

Adım 4: Yaygın 500 Alt Hata Kodları

IIS 500 hatası kendi içinde alt kodlara ayrılır. Bu alt kodları anlamak zaman kazandırır:

  • 500.0: Modül veya ISAPI hatası
  • 500.11: Uygulama kapatılıyor, istek iptal edildi
  • 500.12: Uygulama yeniden başlatılıyor, istek iptal edildi
  • 500.13: Sunucu çok meşgul
  • 500.15: Global.asax dosyasına doğrudan erişim
  • 500.19: web.config yapılandırma hatası (bu çok sık görülür!)
  • 500.21: İşleyici (handler) bulunamadı
  • 500.22: ASP.NET httpHandlers yapılandırma hatası
  • 500.23: ASP.NET httpModules yapılandırma hatası
  • 500.50: RQ_BEGIN_REQUEST phase pipeline hatası
  • 500.100: İç ASP hatası

500.19 web.config hatasını debug etmek:

# web.config sözdizimini doğrula
%windir%system32inetsrvappcmd.exe validate config "Default Web Site/uygulamaAdi"

# Powershell ile appcmd kullan
& "$env:SystemRootsystem32inetsrvappcmd.exe" validate config "Default Web Site"

Adım 5: Uygulama Havuzu Sorunlarını Tespit Et

Uygulama havuzu (Application Pool) sorunları 500 hatalarının önemli bir kaynağı. Özellikle şu durumlar sık yaşanır: yanlış .NET Framework versiyonu, Identity ayarı, veya memory limit aşımı.

# Tum uygulama havuzlarının durumunu listele
Import-Module WebAdministration
Get-WebConfiguration system.applicationHost/applicationPools/add | 
    Select-Object name, state, managedRuntimeVersion, enable32BitAppOnWin64 |
    Format-Table -AutoSize

# Belirli bir uygulama havuzunu yeniden başlat
Restart-WebAppPool -Name "UygulamaHavuzuAdi"

# Durmuz bir uygulama havuzunu başlat
Start-WebAppPool -Name "UygulamaHavuzuAdi"

# Uygulama havuzu event log kayitlarini kontrol et
Get-EventLog -LogName System -Source "WAS" -Newest 20 | Format-List

Uygulama havuzu kimlik (Identity) sorunları:

Çok sık karşılaştığım bir senaryo: uygulama havuzu ApplicationPoolIdentity ile çalışıyor ama dosya sistemine erişmesi gereken bir klasöre izni yok.

# Klasor izinlerini kontrol et
icacls "C:inetpubwwwrootuygulamaAdi"

# IIS_IUSRS grubuna okuma izni ver
icacls "C:inetpubwwwrootuygulamaAdi" /grant "IIS_IUSRS:(OI)(CI)R"

# Yazma izni gereken klasorler icin (upload, temp, log gibi)
icacls "C:inetpubwwwrootuygulamaAdiuploads" /grant "IIS_IUSRS:(OI)(CI)M"

# Uygulama havuzu kimligine ozel izin ver
icacls "C:inetpubwwwrootuygulamaAdi" /grant "IIS AppPoolUygulamaHavuzuAdi:(OI)(CI)F"

Adım 6: ASP.NET Uygulama Hatalarını İzole Et

Eğer ASP.NET uygulaması 500 veriyorsa, hatanın kodun hangi kısmında olduğunu bulmak gerekir.

Global.asax üzerinden hata yakalama:

// Global.asax.cs dosyasina ekle
void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    // Hatayi dosyaya yaz
    System.IO.File.AppendAllText(
        @"C:inetpublogsuygulama_hatalari.txt",
        $"{DateTime.Now}: {ex.ToString()}nn"
    );
}

web.config’de hata sayfası yönlendirmesi:

<configuration>
  <system.web>
    <customErrors mode="On" defaultRedirect="~/hata.aspx">
      <error statusCode="500" redirect="~/sunucu-hatasi.aspx" />
      <error statusCode="404" redirect="~/sayfa-bulunamadi.aspx" />
    </customErrors>
  </system.web>
</configuration>

Powershell ile uygulama logunu izle:

# Anlık log takibi (Linux'taki tail -f gibi)
Get-Content "C:inetpublogsuygulama_hatalari.txt" -Wait -Tail 50

# Son 1 saatte olusan Windows uygulama hatalarini cek
$since = (Get-Date).AddHours(-1)
Get-EventLog -LogName Application -EntryType Error -After $since |
    Select-Object TimeGenerated, Source, EventID, Message |
    Format-List

Adım 7: Gerçek Dünya Senaryoları

Senaryo 1: Upload Sonrası 500 Hatası

Bir e-ticaret sitesinde, kullanıcılar ürün fotoğrafı yüklemeye çalıştığında 500 alıyordu. FREB loguna baktım, hata şuydu: “Access to the path ‘C:inetpubwwwrootmagazauploadstemp’ is denied.”

Çözüm:

# Eksik klasoru olustur
New-Item -ItemType Directory -Path "C:inetpubwwwrootmagazauploadstemp"

# Uygulama havuzu kimligine yazma izni ver
icacls "C:inetpubwwwrootmagazauploads" /grant "IIS AppPoolMagazaPool:(OI)(CI)M"

# IIS'i yeniden baslat
iisreset /noforce

Senaryo 2: web.config 500.19 Hatası

Yeni deploy sonrası site tamamen çökmüştü. 500.19 kodu görünce hemen web.config baktım. Sorun şuydu: yeni eklenen bir HTTP modülü için gerekli IIS feature yüklü değildi.

# Hangi IIS ozelliklerin yuklu oldugunu kontrol et
Get-WindowsFeature -Name Web-* | Where-Object { $_.InstallState -eq "Installed" } | 
    Select-Object Name, DisplayName

# URL Rewrite modulu gibi eksik bir modul varsa yukle
# Once IIS URL Rewrite Module'u Microsoft'tan indir, sonra:
# msiexec /i rewrite_amd64_en-US.msi

# Ya da Windows Feature olarak eklenebilecek moduller icin:
Install-WindowsFeature Web-Http-Redirect
Install-WindowsFeature Web-Basic-Auth

Senaryo 3: .NET Core Uygulaması 500.30 Hatası

.NET Core uygulamalarında 500.30 “ANCM In-Process Start Failure” oldukça yaygın. Bu genellikle uygulamanın başlatılamadığı anlamına gelir.

# stdout log'u etkinlestir (web.config icinde aspNetCore bolumu)
# stdoutLogEnabled="true" yap
# stdoutLogFile=".logsstdout" yap

# Sonra logs klasorunu olustur
New-Item -ItemType Directory -Path "C:inetpubwwwrootnetcoreapplogs"

# Uygulama havuzu kimligine izin ver
icacls "C:inetpubwwwrootnetcoreapplogs" /grant "IIS AppPoolNetCorePool:(OI)(CI)F"

# .NET Core runtime yuklu mu kontrol et
dotnet --list-runtimes

# Hosting Bundle yuklu mu?
Get-ItemProperty HKLM:SoftwareMicrosoftWindowsCurrentVersionUninstall* | 
    Where-Object { $_.DisplayName -like "*Hosting Bundle*" } |
    Select-Object DisplayName, DisplayVersion

Adım 8: IIS Express ile Lokal Debug

Development ortamında IIS Express kullanıyorsan, hata ayıklamayı daha da kolaylaştırabilirsin:

# IIS Express log konumu
%USERPROFILE%DocumentsIISExpresslogs

# applicationhost.config dosyasi
%USERPROFILE%DocumentsIISExpressconfigapplicationhost.config

# Visual Studio ile IIS Express debug icin launchSettings.json
# "ASPNETCORE_ENVIRONMENT": "Development" olduguna emin ol

Adım 9: Proaktif İzleme ve Önleme

Hataları bulduktan sonra, tekrar yaşamamak için izleme kurmalısın:

# Uygulama havuzu crash sayisini izle (Powershell)
$appPools = Get-WebConfiguration system.applicationHost/applicationPools/add
foreach ($pool in $appPools) {
    $crashes = (Get-EventLog -LogName System -Source "WAS" -Newest 100 | 
        Where-Object { $_.Message -like "*$($pool.name)*" -and $_.EntryType -eq "Error" }).Count
    Write-Host "Havuz: $($pool.name) - Son 100 kayit icinde hata: $crashes"
}

# IIS Request Queue uzunlugunu kontrol et
Get-Counter -Counter "Web Service(_Total)Current Connections" -SampleInterval 5 -MaxSamples 12

# Uygulama havuzu memory kullanimi
Get-Counter -Counter "Process(w3wp*)Working Set - Private" |
    Select-Object -ExpandProperty CounterSamples |
    Select-Object InstanceName, CookedValue

Otomatik uygulama havuzu yeniden başlatma scripti:

# Durmuz havuzlari otomatik baslat
$stoppedPools = Get-WebConfiguration system.applicationHost/applicationPools/add | 
    Where-Object { $_.state -eq "Stopped" }

foreach ($pool in $stoppedPools) {
    Write-Host "Baslatiliyor: $($pool.name)"
    Start-WebAppPool -Name $pool.name
    
    # Event log'a yaz
    Write-EventLog -LogName Application -Source "IIS Monitor" -EventId 1001 -EntryType Warning `
        -Message "Uygulama havuzu otomatik baslatildi: $($pool.name)"
}

Bu scripti Task Scheduler’a ekleyip her 5 dakikada bir çalıştırabilirsin. Production’da hayat kurtarır.

Adım 10: Hızlı Kontrol Listesi

500 hatası aldığında sırası ile bunları kontrol et:

  • IIS logunu kontrol et, alt hata koduna bak (500.19, 500.21 gibi)
  • Event Viewer > Application logunu incele, exception detayını bul
  • web.config sözdizimini appcmd ile doğrula
  • Uygulama havuzunun çalışıp çalışmadığını kontrol et
  • Dosya ve klasör izinlerini gözden geçir
  • Failed Request Tracing ile detaylı iz sürme yap
  • Gerekli IIS featureların yüklü olduğunu doğrula
  • Connection string ve dış bağlantıları test et
  • Deploy sonrasıysa, eski versiyona rollback yap ve farkı incele
  • Hata çözüldükten sonra detaylı hata ayıklama ayarlarını geri al

Sonuç

IIS 500 hataları ilk bakışta karmaşık görünse de, sistematik bir yaklaşımla genellikle 15-30 dakika içinde kök nedenine ulaşmak mümkün. En çok zaman kaybettiren şey, doğru yerde bakmamak. Bu yüzden önce logları konuştur: IIS logu, Windows Event Log ve FREB birlikte kullanıldığında neredeyse her zaman sizi doğru yönlendiriyor.

Production ortamında detaylı hata mesajlarını açık bırakmamaya özen göster. Bunun yerine logları ve FREB’i kullan, sorun çözüldükten sonra ayarları eski haline getir. IIS’in sunduğu araçları etkin kullanmak, hata ayıklama sürecini hem hızlandırır hem de daha güvenli hale getirir.

Son olarak şunu söyleyeyim: en iyi hata ayıklama, hatanın oluşmadan önce yapılan izlemedir. Application Pool crash sayacını, memory kullanımını ve request queue’yu düzenli takip edersen, 500 hataları production’da kullanıcılara yansımadan önce müdahale edebilirsin.

Bir yanıt yazın

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