Windows Servis Başlamıyor: Hata Mesajlarını Okuma ve Çözüm Yöntemleri

Bir Windows Server ortamında sabahın 6’sında telefon çalıyor ve karşı taraftaki ses “servisler ayağa kalkmıyor, uygulama çalışmıyor” diyor. Bu senaryoyu yaşamayan sysadmin yoktur. Panik yapmadan önce yapmanız gereken tek şey var: hata mesajlarını doğru okumak. Çünkü Windows, servis başlatma sorunları için oldukça detaylı bilgiler üretiyor, ama bu bilgileri nereden okuyacağınızı bilmiyorsanız karanlıkta el yordamıyla yürümüş olursunuz.

Windows Servis Mimarisini Kısaca Anlamak

Hata ayıklamaya geçmeden önce servis mimarisini kafanızda oturtmak önemli. Windows servisleri, Service Control Manager (SCM) tarafından yönetilir. SCM, services.exe prosesi altında çalışır ve servislerin başlatılması, durdurulması, yeniden başlatılması gibi tüm yaşam döngüsünü kontrol eder.

Bir servis başlatılamadığında SCM şu sırayla işlemler gerçekleştirir:

  • Servis binary dosyasını çalıştırmayı dener
  • Servisten başarılı başlatma bildirimi bekler (varsayılan timeout 30 saniyedir)
  • Belirtilen sürede yanıt gelmezse başlatma işlemini iptal eder
  • Hata kodunu Event Log’a yazar
  • Dependency varsa, bağımlı servisleri de başlatmaz

Bu akışı bilmek, hata mesajlarını yorumlarken büyük kolaylık sağlar.

İlk Başvuru Noktası: Event Viewer

Bir servis başlamıyorsa ilk bakacağınız yer Windows Event Viewer‘dır. Services.msc üzerinden gördüğünüz hata mesajı genellikle çok genel kalır. Gerçek detay Event Log’dadır.

Event Viewer’ı açmak için:

# Run dialogundan veya PowerShell'den
eventvwr.msc

İlgilenmeniz gereken log lokasyonları:

  • Windows Logs > System: SCM hataları, genel sistem servisi sorunları
  • Windows Logs > Application: Uygulamaya özgü servis hataları
  • Applications and Services Logs: SQL Server, IIS, Exchange gibi uygulamaların özel logları

System log altında, başarısız olan servis için genellikle şu kaynaklardan event göreceksiniz: Service Control Manager ve Service Control Manager Errors.

PowerShell ile Event Log Okuma

GUI yerine PowerShell kullanmak, özellikle Core kurulumlarında veya remote sunucularda çok daha pratiktir.

# Son 50 System log eventini göster
Get-EventLog -LogName System -Newest 50 | Where-Object {$_.Source -like "*Service*"}
# Belirli bir servise ait hataları filtrele (örnek: wuauserv - Windows Update)
Get-EventLog -LogName System -Source "Service Control Manager" -EntryType Error -Newest 20 | 
Select-Object TimeGenerated, EventID, Message | 
Format-List
# Daha gelişmiş filtreleme için Get-WinEvent kullan
Get-WinEvent -FilterHashtable @{
    LogName = 'System'
    ProviderName = 'Service Control Manager'
    Level = 2  # Error
    StartTime = (Get-Date).AddHours(-24)
} | Select-Object TimeCreated, Id, Message | Format-List

Bu komutlardan çıkan çıktıda dikkat etmeniz gereken alanlar: EventID, Message ve TimeGenerated. EventID, sorunun kategorisini anlamanızda kritik rol oynar.

Kritik Event ID’leri ve Anlamları

Bazı Event ID’leri sysadmin hayatında çok sık karşınıza çıkacak:

  • 7000: Servis başlatılamadı (başlatma hatası)
  • 7001: Bağımlı servis çalışmadığı için servis başlatılamadı
  • 7002: Başlatma sırasında dependency zinciri kırıldı
  • 7009: Timeout, servis başlatma sinyali göndermedi
  • 7011: Transaction timeout, servis zamanında yanıt vermedi
  • 7023: Servis bir hata ile sonlandı
  • 7024: Servis özel bir hata koduyla sonlandı
  • 7034: Servis beklenmedik şekilde sonlandı
  • 7038: Servis belirtilen kullanıcı hesabıyla oturum açamadı
  • 7040: Servis başlatma tipi değiştirildi

Event ID 7038 özellikle servis hesabı sorunlarında karşınıza çıkar ve çözümü çoğunlukla basittir ama sizi saatlerce uğraştırabilir.

Hata Kodu Çözümleme: Win32 Exit Kodları

Event Log mesajında sıkça şunu görürsünüz: The service terminated with service-specific error code X veya Error Code: 0x8007XXXX. Bu kodları anlamak için net helpmsg komutundan yararlanın.

# Örnek: 1053 hata kodunu çöz
net helpmsg 1053
# Çıktı: The service did not respond to the start or control request in a timely fashion.

# Başka bir örnek
net helpmsg 1067
# Çıktı: The process terminated unexpectedly.
# PowerShell ile daha detaylı hata mesajı
$errorCode = 1053
[System.ComponentModel.Win32Exception]$errorCode

Hex kodları için önce decimal’e çevirmeniz gerekir. 0x80070005 gibi kodlar için:

# Hex'ten decimal'e çevirip anlamını bul
$hexCode = "0x80070005"
$decimal = [Convert]::ToInt32($hexCode, 16)
Write-Host "Decimal: $decimal"
net helpmsg ($decimal -band 0xFFFF)
# 0x80070005 = Access Denied

Servis Durumunu ve Bağımlılıkları Kontrol Etme

Bir servis başlamıyorsa, önce bağımlılıklarını kontrol edin. Bağımlı olduğu bir servis çalışmıyorsa, o servis de başlamayacaktır.

# Servis bağımlılıklarını göster (örnek: MSSQLSERVER)
Get-Service -Name MSSQLSERVER -DependentServices
Get-Service -Name MSSQLSERVER -RequiredServices

# Daha detaylı görünüm
$service = Get-WmiObject -Class Win32_Service -Filter "Name='MSSQLSERVER'"
$service.StartService()
# sc.exe ile bağımlılık zincirini göster
sc qc "MSSQLSERVER"
# OUTPUT'ta: DEPENDENCIES bölümüne bakın

Bağımlılık sorununu çözdükten sonra servisin başlayıp başlamadığını test edin:

# Servisi başlat ve durumunu izle
Start-Service -Name "ServiceAdi" -PassThru | 
    Wait-Service -Timeout 30 -ErrorAction SilentlyContinue

# Servisi başlat ve anlık durum logla
$startTime = Get-Date
Start-Service "ServiceAdi"
$endTime = Get-Date
Write-Host "Servis başlatma süresi: $(($endTime - $startTime).TotalSeconds) saniye"
Get-Service "ServiceAdi" | Select-Object Name, Status, StartType

Gerçek Dünya Senaryosu 1: SQL Server Servisi Başlamıyor

Klasik senaryo: Production SQL Server instance’ı sabah başlamıyor, Event Log’da şunu görüyorsunuz:

Event ID: 7038
The MSSQLSERVER service was unable to log on as .SQLServiceAccount with 
the currently configured password due to the following error:
Logon failure: the user has not been granted the requested logon type at this computer.

Bu, servis hesabının şifresinin değiştiği veya “Log on as a service” izninin kaldırıldığı anlamına gelir. Çözüm adımları:

# Servis hesabının "Log on as a service" hakkını kontrol et
secedit /export /cfg C:tempsecpol.cfg
Get-Content C:tempsecpol.cfg | Select-String "SeServiceLogonRight"

Eğer hesap listede yoksa, Local Security Policy üzerinden eklemeniz gerekir. Alternatif olarak PowerShell ile:

# NTRights aracı yoksa, bir PowerShell fonksiyonu yazabiliriz
# Önce mevcut izinleri listeleyelim
$computer = [ADSI]"WinNT://$env:COMPUTERNAME"
# ya da doğrudan services.msc'den servis hesabını güncelleyin

# Servis hesabını ve şifresini sc.exe ile güncelle
sc.exe config MSSQLSERVER obj= ".YeniHesap" password= "YeniSifre123!"

# Değişikliği uygula ve servisi başlat
sc.exe start MSSQLSERVER

Gerçek Dünya Senaryosu 2: IIS Application Pool Tiplemeleri

IIS W3SVC servisi başlamıyor, Event ID 7000 geliyor. Application Event Log’a baktığınızda şunu görüyorsunuz:

The World Wide Web Publishing Service service failed to start due to the following error:
The service did not start due to a logon failure.

Bu durumda önce IIS loglarına bakmak gerekir:

# IIS servis durumu
Get-Service W3SVC, WAS | Select-Object Name, Status, StartType

# HTTP.sys durumu kontrol
netsh http show servicestate

# IIS config dosyasını doğrula
%windir%system32inetsrvappcmd.exe list site
%windir%system32inetsrvappcmd.exe list apppool
# Application Pool identity sorunlarını tespit et
Import-Module WebAdministration
Get-WebConfiguration system.applicationHost/applicationPools/add | 
    Select-Object name, @{n="Identity";e={$_.processModel.userName}} |
    Format-Table -AutoSize

Process Monitor ile Derinlemesine Analiz

Bazen Event Log yeterli bilgi vermez. Özellikle binary’nin bulunamaması veya DLL eksikliği gibi durumlarda Process Monitor (ProcMon) kullanmanız gerekir.

Procmon’u çalıştıramadığınız durumlarda veya hızlı bir alternatif olarak, servisin binary yolunu ve dosya izinlerini kontrol edin:

# Servisin executable yolunu bul
sc qc "ProblematikServis" | Select-String "BINARY_PATH_NAME"

# Ya da PowerShell ile
Get-WmiObject Win32_Service -Filter "Name='ProblematikServis'" | 
    Select-Object Name, PathName, StartName

# Dosya var mı kontrol et
$servicePath = (Get-WmiObject Win32_Service -Filter "Name='ProblematikServis'").PathName
# Tırnak işaretlerini temizle
$cleanPath = $servicePath -replace '"', '' -replace ' .*$', ''
Test-Path $cleanPath
# Dosya izinlerini kontrol et
$servicePath = "C:Program FilesMyAppmyservice.exe"
$acl = Get-Acl $servicePath
$acl.Access | Select-Object IdentityReference, FileSystemRights, AccessControlType | 
    Format-Table -AutoSize

# LOCAL SERVICE ve NETWORK SERVICE hesaplarının erişimi var mı?
$acl.Access | Where-Object {$_.IdentityReference -match "SERVICE"}

Registry Kontrolleri

Bazı servis başlatma sorunları registry kayıtlarındaki bozulmalardan kaynaklanır. Windows servisleri HKLM:SYSTEMCurrentControlSetServices altında kayıtlıdır.

# Servis registry kaydını görüntüle
$serviceName = "Spooler"
Get-ItemProperty "HKLM:SYSTEMCurrentControlSetServices$serviceName" |
    Select-Object ImagePath, Start, Type, ObjectName | Format-List

# Start değerleri:
# 0 = Boot
# 1 = System
# 2 = Automatic
# 3 = Manual
# 4 = Disabled

# Bozuk ImagePath'i onar (örnek)
Set-ItemProperty "HKLM:SYSTEMCurrentControlSetServices$serviceName" `
    -Name "ImagePath" `
    -Value "C:WindowsSystem32spoolsv.exe"

Timeout Sorunları ve SCM Yapılandırması

Büyük uygulamaların servisleri bazen 30 saniyelik varsayılan timeout süresini aşabilir. Bu durumda Event ID 7009 alırsınız. SCM timeout’unu artırmak için:

# Mevcut SCM timeout değerini kontrol et
Get-ItemProperty "HKLM:SYSTEMCurrentControlSetControl" -Name ServicesPipeTimeout

# Timeout'u 60 saniyeye çıkar (milisaniye cinsinden)
Set-ItemProperty "HKLM:SYSTEMCurrentControlSetControl" `
    -Name "ServicesPipeTimeout" `
    -Value 60000 `
    -Type DWord

# Değişiklik için sistem yeniden başlatma gerekli
Write-Host "Değişiklik için sistemi yeniden başlatın"

Dikkat: Bu değeri gereğinden fazla artırmak, sistem başlatma süresini uzatır. Makul bir üst limit 120 saniyedir (120000ms).

Servis Recovery Ayarları ve Otomatik Kurtarma

Bir servis crash olduğunda otomatik kurtarma aksiyonlarını yapılandırmak, özellikle kritik servislerde önemlidir:

# Mevcut recovery ayarlarını görüntüle
sc qfailure "ServiceAdi"

# Recovery ayarlarını yapılandır:
# İlk başarısızlıkta: Yeniden başlat
# İkinci başarısızlıkta: Yeniden başlat
# Sonraki başarısızlıklarda: Yeniden başlat
# Reset count: 1 gün
# Restart delay: 60 saniye

sc failure "ServiceAdi" reset= 86400 actions= restart/60000/restart/60000/restart/60000
# PowerShell ile daha modern yaklaşım
$service = Get-Service "ServiceAdi"

# Failure actions için COM nesnesini kullan
# veya sc.exe komutunu PowerShell'den çağır
& sc.exe failure $service.Name reset= 86400 actions= restart/30000/restart/60000/run/1000
& sc.exe failureflag $service.Name 1  # Non-crash failures da recovery'yi tetiklesin

Diagnostic Tool: SFC ve DISM

Servis binary’si veya sistem DLL’leri bozulmuşsa, servis hiçbir zaman başlamaz. Bu durumda sistem dosyası onarımı gerekir:

# System File Checker çalıştır
sfc /scannow

# Sonucu kontrol et
# "Windows Resource Protection found corrupt files and repaired them" 
# mesajı görürseniz sorun çözülmüş olabilir

# DISM ile Windows image onarımı
DISM /Online /Cleanup-Image /RestoreHealth

# DISM logunu incele
Get-Content C:WindowsLogsDISMdism.log | Select-Object -Last 50

Hızlı Tanılama Checklist

Bir servis başlamıyorsa şu sırayla kontrol edin:

  • Event Viewer System Log: EventID 7000-7040 arası kayıtlar
  • Event Viewer Application Log: Uygulamaya özgü detaylı hata
  • Servis hesabı: Şifre değişikliği, hesap kilidi, izin eksikliği
  • Binary dosyası: Mevcut mu, izinler doğru mu
  • Bağımlılıklar: Tüm required servisler çalışıyor mu
  • Port/resource çakışması: Başka bir process gerekli portu kullanıyor mu
  • Disk alanı: Log ve temp dizinlerinde yeterli alan var mı
  • Registry: Servis kaydı bozuk mu
  • Antivirus: Binary’yi bloklayan bir kural var mı
  • Windows Updates: Son güncelleme sonrası sorun başladıysa rollback değerlendirilebilir
# Hızlı tanılama scripti - tüm durmuş Automatic servisleri listele
Get-Service | 
    Where-Object {$_.StartType -eq 'Automatic' -and $_.Status -ne 'Running'} | 
    Select-Object Name, DisplayName, Status, StartType |
    Format-Table -AutoSize
# Belirli bir servis için tam tanılama
function Diagnose-Service {
    param([string]$ServiceName)
    
    Write-Host "=== Servis Bilgisi ===" -ForegroundColor Cyan
    Get-Service $ServiceName | Select-Object *
    
    Write-Host "`n=== WMI Detayları ===" -ForegroundColor Cyan
    Get-WmiObject Win32_Service -Filter "Name='$ServiceName'" | 
        Select-Object Name, PathName, StartName, State, ExitCode
    
    Write-Host "`n=== Son 10 Event ===" -ForegroundColor Cyan
    Get-EventLog -LogName System -Source "Service Control Manager" -Newest 10 | 
        Where-Object {$_.Message -like "*$ServiceName*"} | 
        Select-Object TimeGenerated, EventID, Message | Format-List
    
    Write-Host "`n=== Bağımlılıklar ===" -ForegroundColor Cyan
    Get-Service $ServiceName -RequiredServices | Select-Object Name, Status
}

Diagnose-Service -ServiceName "MSSQLSERVER"

Sonuç

Windows servis sorunları, paniğin değil metodolojinin çözüme götürdüğü durumlardır. Event Viewer’daki EventID’ler ve hata mesajları size çok net bir yol haritası sunar, yeter ki bu mesajları okumayı bilin. net helpmsg ile hata kodlarını çevirmek, PowerShell ile event filtresi yapmak ve servis bağımlılık zincirini takip etmek, vaka başına harcadığınız süreyi ciddi ölçüde kısaltır.

En sık karşılaşacağınız senaryolar servis hesabı sorunları, binary bulunamama hataları ve dependency zinciri kopukluklarıdır. Bu üç kategoriyi kafanıza oturttuğunuzda, vakaların büyük çoğunluğunu 10 dakikada çözebilir duruma gelirsiniz.

Son olarak, production ortamında yaşanan her servis sorununu bir öğrenme fırsatı olarak değerlendirin. Sorunu çözdükten sonra root cause’u belgeleyin ve bir daha aynı sorunla karşılaşmamak için monitoring, alerting veya recovery yapılandırması gibi proaktif adımlar atın. Reaktif çalışmaktan proaktif çalışmaya geçiş, iyi bir sysadmin’i mükemmel bir sysadmin’den ayıran çizgidir.

Bir yanıt yazın

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