IIS yönetimi denince aklıma hep o eski günler gelir: sunucuya RDP bağlan, IIS Manager’ı aç, tıkla tıkla tıkla… Onlarca sunucuda aynı işlemi tekrarla. Artık o günler geride kaldı. PowerShell ile IIS yönetimi, hem zaman kazandırıyor hem de tutarlı konfigürasyonlar sağlıyor. Bu yazıda gerçek dünya senaryolarıyla PowerShell üzerinden IIS’i nasıl yöneteceğinizi adım adım ele alacağız.
Başlamadan Önce: WebAdministration Modülü
PowerShell ile IIS yönetmek için öncelikle WebAdministration modülünün yüklü olması gerekiyor. Windows Server 2012 ve sonrasında bu modül IIS kurulumunun bir parçası olarak geliyor. Ama önce kontrol edelim:
# Modülün mevcut olup olmadığını kontrol et
Get-Module -ListAvailable -Name WebAdministration
# Modülü import et
Import-Module WebAdministration
# Alternatif olarak IISAdministration modülü (daha yeni, daha güçlü)
Import-Module IISAdministration
WebAdministration modülü, IIS’i bir sürücü gibi ele almanızı sağlıyor. IIS: sürücüsü üzerinden dosya sistemi mantığıyla gezinebilirsiniz. IISAdministration modülü ise daha modern bir yaklaşım sunuyor ve IIS 10 ile gelen yenilikleri destekliyor. Ben genellikle her ikisini de kullanıyorum; hangisi işe daha uygunsa onu tercih ediyorum.
IIS rolü yüklü değilse şu komutla kurabilirsiniz:
# IIS ve yönetim araçlarını kur
Install-WindowsFeature -Name Web-Server -IncludeManagementTools -IncludeAllSubFeature
# Sadece belirli özellikleri eklemek istiyorsanız
Install-WindowsFeature -Name Web-Server, Web-WebServer, Web-Common-Http, Web-Static-Content, Web-Default-Doc, Web-Dir-Browsing, Web-Http-Errors, Web-App-Dev, Web-Asp-Net45, Web-CGI, Web-Health, Web-Http-Logging, Web-Log-Libraries, Web-Request-Monitor, Web-Security, Web-Filtering, Web-Performance, Web-Stat-Compression, Web-Mgmt-Tools, Web-Mgmt-Console
IIS Durumu ve Mevcut Siteleri Görüntüleme
Sunucuya bağlandığınızda ilk yapmanız gereken mevcut durumu anlamak. Hangi siteler var, hangileri çalışıyor, hangileri durmuş?
# Tüm web sitelerini listele
Get-Website
# Sadece çalışan siteleri göster
Get-Website | Where-Object { $_.State -eq "Started" }
# Belirli bir sitenin detaylarını göster
Get-Website -Name "Default Web Site"
# Application Pool'ları listele
Get-WebConfiguration -Filter "system.applicationHost/applicationPools/add" |
Select-Object name, state, managedRuntimeVersion, managedPipelineMode
# Daha kısa yol
Get-WebConfigurationProperty -Filter "system.applicationHost/applicationPools/add" -Name "." |
Select-Object name, @{n="State"; e={$_.state}}
Bu komutları çalıştırdığınızda sitenin adı, ID’si, durumu, bağlama bilgileri ve fiziksel yolu gibi kritik bilgilere ulaşırsınız. Özellikle birden fazla sitenin çalıştığı production ortamlarında bu bilgiler çok değerli.
Yeni Web Sitesi Oluşturma
Diyelim ki yeni bir uygulama deploy edeceksiniz. GUI ile yapmak yerine PowerShell ile yapalım. Bu sayede aynı konfigürasyonu test, staging ve production ortamlarına kolayca uygulayabilirsiniz.
# Önce fiziksel dizini oluştur
$sitePath = "C:inetpubwwwrootYeniUygulama"
New-Item -ItemType Directory -Path $sitePath -Force
# Yeni web sitesi oluştur
New-Website -Name "YeniUygulama" `
-Port 8080 `
-PhysicalPath $sitePath `
-ApplicationPool "DefaultAppPool" `
-HostHeader "yeniuygulama.sirket.local"
# HTTPS binding ekle (SSL sertifikası zaten yüklüyse)
New-WebBinding -Name "YeniUygulama" `
-Protocol "https" `
-Port 443 `
-HostHeader "yeniuygulama.sirket.local" `
-SslFlags 1
# Siteyi başlat
Start-Website -Name "YeniUygulama"
# Durumu kontrol et
Get-Website -Name "YeniUygulama" | Select-Object Name, State, PhysicalPath
Burada dikkat edilmesi gereken nokta, -SslFlags 1 parametresi SNI (Server Name Indication) kullanımını aktif ediyor. Birden fazla HTTPS sitesi çalıştırıyorsanız bu şart.
Application Pool Yönetimi
Application Pool’lar IIS’in kalbi. Yanlış konfigürasyon hem güvenlik açığı hem de performans sorunu yaratır. Özellikle çok kiracılı ortamlarda her uygulamanın kendi pool’unda çalışması kritik.
# Yeni Application Pool oluştur
New-WebAppPool -Name "YeniUygulamaPool"
# Pool özelliklerini yapılandır
Set-ItemProperty -Path "IIS:AppPoolsYeniUygulamaPool" `
-Name processModel `
-Value @{
userName = "IIS AppPoolYeniUygulamaPool"
password = ""
identityType = 4 # ApplicationPoolIdentity
}
# .NET Runtime versiyonunu ayarla
Set-ItemProperty -Path "IIS:AppPoolsYeniUygulamaPool" `
-Name managedRuntimeVersion `
-Value "v4.0"
# 32-bit uygulamalar için
Set-ItemProperty -Path "IIS:AppPoolsYeniUygulamaPool" `
-Name enable32BitAppOnWin64 `
-Value $true
# Idle timeout'u ayarla (dakika cinsinden, 0 = devre dışı)
Set-ItemProperty -Path "IIS:AppPoolsYeniUygulamaPool" `
-Name processModel.idleTimeout `
-Value "00:00:00"
# Recycling ayarları - günlük belirli saatte recycle
Set-ItemProperty -Path "IIS:AppPoolsYeniUygulamaPool" `
-Name recycling.periodicRestart.schedule `
-Value @{value = "03:00:00"}
# Pool'u siteye ata
Set-ItemProperty -Path "IIS:SitesYeniUygulama" `
-Name applicationPool `
-Value "YeniUygulamaPool"
Production’da identityType = 4 yani ApplicationPoolIdentity kullanmanızı kesinlikle öneririm. NetworkService veya LocalSystem kullanmak gereksiz yetki vermek demek.
Toplu Yönetim Senaryosu: Tüm Siteleri Durdur ve Başlat
Bakım penceresi açıyorsunuz ve sunucudaki tüm siteleri durdurmanız lazım. GUI ile tek tek yapmak yerine:
# Tüm siteleri durdur (Default Web Site hariç)
Get-Website | Where-Object { $_.Name -ne "Default Web Site" } | Stop-Website
# Tüm Application Pool'ları durdur
Get-ChildItem "IIS:AppPools" | Where-Object { $_.State -eq "Started" } | Stop-WebAppPool
# Bakım işlemlerini yap...
# Sonra geri başlat
# Tüm pool'ları başlat
Get-ChildItem "IIS:AppPools" | Where-Object { $_.State -eq "Stopped" } | Start-WebAppPool
# Tüm siteleri başlat
Get-Website | Where-Object { $_.State -eq "Stopped" } | Start-Website
# Durumları raporla
Write-Host "=== Site Durumları ===" -ForegroundColor Cyan
Get-Website | Select-Object Name, State | Format-Table -AutoSize
Write-Host "=== Pool Durumları ===" -ForegroundColor Cyan
Get-ChildItem "IIS:AppPools" | Select-Object Name, State | Format-Table -AutoSize
SSL Sertifikası Bağlama ve Yönetimi
HTTPS olmadan web sunucusu olmaz. SSL sertifikalarını PowerShell ile yönetmek başlangıçta karmaşık görünse de bir kez alıştıktan sonra çok pratik oluyor.
# Yüklü sertifikaları listele
Get-ChildItem -Path "Cert:LocalMachineMy" |
Select-Object Subject, Thumbprint, NotAfter |
Sort-Object NotAfter
# 30 gün içinde süresi dolacak sertifikaları bul (monitoring için harika)
$uyariGunu = 30
Get-ChildItem -Path "Cert:LocalMachineMy" |
Where-Object { $_.NotAfter -lt (Get-Date).AddDays($uyariGunu) } |
Select-Object Subject, Thumbprint, NotAfter |
ForEach-Object {
Write-Warning "Sertifika yakında sona eriyor: $($_.Subject) - $($_.NotAfter)"
}
# Sertifikayı HTTPS binding'e bağla
$thumbprint = "BURAYA_SERTIFIKA_THUMBPRINT_YAZIN"
$siteName = "YeniUygulama"
$port = 443
$hostHeader = "yeniuygulama.sirket.local"
# Önce mevcut binding'i kaldır (varsa)
Remove-WebBinding -Name $siteName -Protocol "https" -Port $port -ErrorAction SilentlyContinue
# Yeni binding ekle
New-WebBinding -Name $siteName `
-Protocol "https" `
-Port $port `
-HostHeader $hostHeader `
-SslFlags 1
# Sertifikayı binding'e ata
$binding = Get-WebBinding -Name $siteName -Protocol "https"
$binding.AddSslCertificate($thumbprint, "My")
Write-Host "SSL sertifikası başarıyla bağlandı." -ForegroundColor Green
IIS Log Yönetimi ve Analizi
IIS logları disk doldurmaya bayılır. Özellikle yoğun sitelerde günde gigabyte’larca log oluşabilir. Hem log rotasyonunu yönetmek hem de anlık analiz yapmak için PowerShell kullanıyorum.
# Log dizinini bul
$logPath = (Get-WebConfigurationProperty -Filter "system.applicationHost/sites/siteDefaults/logFile" `
-Name directory).Value
Write-Host "Log dizini: $logPath"
# Son 7 günün log dosyalarını listele
Get-ChildItem -Path $logPath -Recurse -Filter "*.log" |
Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } |
Select-Object FullName,
@{n="BoyutMB"; e={[math]::Round($_.Length/1MB, 2)}},
LastWriteTime |
Sort-Object LastWriteTime -Descending
# 30 günden eski logları arşivle ve sil
$eskiLoglar = Get-ChildItem -Path $logPath -Recurse -Filter "*.log" |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) }
foreach ($log in $eskiLoglar) {
Write-Host "Siliniyor: $($log.FullName)" -ForegroundColor Yellow
Remove-Item -Path $log.FullName -Force
}
Write-Host "Temizlenen log sayısı: $($eskiLoglar.Count)" -ForegroundColor Green
# Basit log analizi - en çok 404 alan URL'leri bul
$bugunLog = Get-ChildItem -Path $logPath -Recurse -Filter "*.log" |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
if ($bugunLog) {
Get-Content $bugunLog.FullName |
Where-Object { $_ -notlike "#*" -and $_ -like "*404*" } |
ForEach-Object { ($_ -split " ")[4] } |
Group-Object |
Sort-Object Count -Descending |
Select-Object -First 10 |
ForEach-Object { Write-Host "404: $($_.Name) - $($_.Count) kez" }
}
Kapsamlı Monitoring Scripti
Gerçek dünya senaryosu: Her sabah işe geldiğinizde IIS’in durumunu kontrol etmek istiyorsunuz. Bu scripti Task Scheduler ile otomatize edin, e-posta ile günlük rapor alın.
# IIS-HealthCheck.ps1
# Her gün sabah 07:00'de çalışacak şekilde planla
param(
[string]$RaporDizini = "C:LogsIIS-Raporlar",
[string]$EpostaAlici = "[email protected]"
)
Import-Module WebAdministration -ErrorAction Stop
$tarih = Get-Date -Format "yyyy-MM-dd"
$rapor = @()
$uyarilar = @()
# Site durumlarını kontrol et
$siteler = Get-Website
foreach ($site in $siteler) {
$durumBilgi = [PSCustomObject]@{
SiteAdi = $site.Name
Durum = $site.State
Port = ($site.Bindings.Collection | Select-Object -First 1).bindingInformation
FizikselYol = $site.PhysicalPath
Fiziksel_Mevcut = Test-Path $site.PhysicalPath
}
$rapor += $durumBilgi
if ($site.State -ne "Started") {
$uyarilar += "UYARI: $($site.Name) sitesi çalışmıyor! Durum: $($site.State)"
}
if (-not (Test-Path $site.PhysicalPath)) {
$uyarilar += "KRITIK: $($site.Name) sitesinin fiziksel dizini bulunamadı: $($site.PhysicalPath)"
}
}
# Application Pool durumlarını kontrol et
$poollar = Get-ChildItem "IIS:AppPools"
foreach ($pool in $poollar) {
if ($pool.State -ne "Started") {
$uyarilar += "UYARI: $($pool.Name) Application Pool çalışmıyor!"
# Durmuş pool'u otomatik başlat
try {
Start-WebAppPool -Name $pool.Name
$uyarilar += "BILGI: $($pool.Name) pool otomatik başlatıldı."
} catch {
$uyarilar += "HATA: $($pool.Name) pool başlatılamadı: $($_.Exception.Message)"
}
}
}
# Sertifika kontrolü
$sertifikalar = Get-ChildItem -Path "Cert:LocalMachineMy" |
Where-Object { $_.NotAfter -lt (Get-Date).AddDays(30) }
foreach ($cert in $sertifikalar) {
$kalanGun = ($cert.NotAfter - (Get-Date)).Days
$uyarilar += "SERTIFIKA UYARISI: $($cert.Subject) sertifikasının süresi $kalanGun gün sonra doluyor!"
}
# Raporu kaydet
if (-not (Test-Path $RaporDizini)) {
New-Item -ItemType Directory -Path $RaporDizini -Force | Out-Null
}
$raporDosya = Join-Path $RaporDizini "IIS-Rapor-$tarih.txt"
$rapor | Format-Table -AutoSize | Out-String | Out-File $raporDosya
if ($uyarilar.Count -gt 0) {
Add-Content -Path $raporDosya -Value "`n=== UYARILAR ==="
$uyarilar | ForEach-Object { Add-Content -Path $raporDosya -Value $_ }
Write-Warning "Toplam $($uyarilar.Count) uyarı tespit edildi."
} else {
Write-Host "Tüm sistemler normal çalışıyor." -ForegroundColor Green
}
# Konsola özet bas
Write-Host "`n=== IIS Health Check Özeti - $tarih ===" -ForegroundColor Cyan
$rapor | Format-Table -AutoSize
if ($uyarilar.Count -gt 0) {
$uyarilar | ForEach-Object { Write-Warning $_ }
}
Web.config Yönetimi PowerShell ile
Web.config değişiklikleri manuel olarak hataya açık. PowerShell ile programatik olarak yönetin:
# Connection string ekle veya güncelle
$siteName = "YeniUygulama"
$connStringAdi = "VeriTabaniConn"
$connStringDeger = "Server=db01;Database=UygulamaDB;Integrated Security=True;"
# Mevcut connection string'i kaldır (varsa)
Remove-WebConfigurationProperty -PSPath "IIS:Sites$siteName" `
-Filter "connectionStrings" `
-Name "." `
-AtElement @{name=$connStringAdi} `
-ErrorAction SilentlyContinue
# Yeni connection string ekle
Add-WebConfigurationProperty -PSPath "IIS:Sites$siteName" `
-Filter "connectionStrings" `
-Name "." `
-Value @{
name = $connStringAdi
connectionString = $connStringDeger
providerName = "System.Data.SqlClient"
}
# AppSettings değeri ekle/güncelle
Set-WebConfigurationProperty -PSPath "IIS:Sites$siteName" `
-Filter "appSettings/add[@key='OrtamAdi']" `
-Name "value" `
-Value "Production"
# Custom error sayfaları ayarla
Set-WebConfigurationProperty -PSPath "IIS:Sites$siteName" `
-Filter "system.web/customErrors" `
-Name "mode" `
-Value "On"
Write-Host "Web.config başarıyla güncellendi." -ForegroundColor Green
URL Rewrite Kuralları
URL yönlendirme kuralları modern web uygulamalarının olmazsa olmazı. PowerShell ile bu kuralları da yönetebilirsiniz:
# URL Rewrite modülünün yüklü olduğunu kontrol et
if (-not (Get-Module -ListAvailable -Name "WebAdministration")) {
Write-Error "WebAdministration modülü bulunamadı!"
exit
}
$siteName = "YeniUygulama"
# HTTP'den HTTPS'e yönlendirme kuralı ekle
Add-WebConfigurationProperty -PSPath "IIS:Sites$siteName" `
-Filter "system.webServer/rewrite/rules" `
-Name "." `
-Value @{
name = "HTTP to HTTPS Redirect"
stopProcessing = "True"
match = @{ url = "(.*)" }
conditions = @{
add = @{
input = "{HTTPS}"
pattern = "^OFF$"
}
}
action = @{
type = "Redirect"
url = "https://{HTTP_HOST}/{R:1}"
redirectType = "Permanent"
}
}
# Mevcut rewrite kurallarını listele
Get-WebConfigurationProperty -PSPath "IIS:Sites$siteName" `
-Filter "system.webServer/rewrite/rules/rule" `
-Name "name" |
ForEach-Object { Write-Host "Kural: $($_.Value)" }
Sık Karşılaşılan Sorunlar ve Çözümleri
Yıllarca IIS yönetirken tekrar eden sorunlarla karşılaştım. İşte en yaygın olanları ve PowerShell ile hızlı çözümleri:
Application Pool Otomatik Durdurma Sorunu
Pool’ların neden durduğunu anlamak için event log’a bakın:
# IIS ile ilgili event log kayıtlarını filtrele
Get-EventLog -LogName Application -Source "IIS*" -Newest 50 |
Select-Object TimeGenerated, EntryType, Message |
Where-Object { $_.EntryType -eq "Error" -or $_.EntryType -eq "Warning" } |
Format-List
# Application Pool crash sayısını kontrol et
Get-WebConfiguration -Filter "system.applicationHost/applicationPools/add" |
ForEach-Object {
$poolAdi = $_.name
$rapidFailCount = (Get-ItemProperty "IIS:AppPools$poolAdi" `
-Name failure.rapidFailProtection).Value
Write-Host "$poolAdi - Rapid Fail Protection: $rapidFailCount"
}
İzin Sorunları
Dizin izinlerini PowerShell ile hızlıca düzeltin:
# Application Pool identity'sine dizin izni ver
$sitePath = "C:inetpubwwwrootYeniUygulama"
$poolAdi = "YeniUygulamaPool"
$acl = Get-Acl $sitePath
$identityName = "IIS AppPool$poolAdi"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
$identityName,
"ReadAndExecute",
"ContainerInherit,ObjectInherit",
"None",
"Allow"
)
$acl.SetAccessRule($accessRule)
Set-Acl -Path $sitePath -AclObject $acl
Write-Host "$identityName için izinler ayarlandı." -ForegroundColor Green
Uzak Sunucu Yönetimi
Tek sunucu yönetmek kolay. Ama 10-20 sunucunuz varsa? PowerShell Remoting devreye giriyor:
# Uzak sunucularda IIS durumunu kontrol et
$sunucular = @("webserver01", "webserver02", "webserver03")
$sonuclar = Invoke-Command -ComputerName $sunucular -ScriptBlock {
Import-Module WebAdministration
$siteler = Get-Website | Select-Object Name, State
$poollar = Get-ChildItem "IIS:AppPools" |
Where-Object {$_.State -ne "Started"} |
Select-Object Name, State
[PSCustomObject]@{
Sunucu = $env:COMPUTERNAME
Siteler = $siteler
DurmuşPoollar = $poollar
}
} -Credential (Get-Credential)
foreach ($sonuc in $sonuclar) {
Write-Host "`n=== $($sonuc.Sunucu) ===" -ForegroundColor Cyan
$sonuc.Siteler | Format-Table -AutoSize
if ($sonuc.DurmuşPoollar) {
Write-Warning "Durmuş poollar var!"
$sonuc.DurmuşPoollar | Format-Table -AutoSize
}
}
Sonuç
PowerShell ile IIS yönetimi, başlangıçta öğrenme eğrisi gerektirse de uzun vadede inanılmaz verimlilik sağlıyor. Bu yazıda ele aldığımız konuları özetlersek:
- WebAdministration ve IISAdministration modülleri temel başlangıç noktanız. Her ikisini de tanıyın.
- Site ve Application Pool oluşturma işlemlerini script haline getirin. Aynı konfigürasyonu tekrar kullanmak hem hata riskini azaltır hem de zaman kazandırır.
- SSL sertifika yönetimi ve süresi dolmak üzere olan sertifikaları proaktif olarak takip etmek büyük bir kazanç.
- Log yönetimi ihmal edilmesi disk dolu hatasına en hızlı giden yol. Otomatize edin.
- Health check scriptleri gece yarısı telefon almak yerine sabah güzel bir e-posta almayı tercih ederseniz şart.
- Uzak yönetim çok sunuculu ortamlarda PowerShell Remoting ile tek noktadan kontrol sağlar.
Bu scriptlerin tamamını bir Git repository’sinde tutmanızı şiddetle tavsiye ederim. Hem versiyon takibi yaparsınız hem de ekip arkadaşlarınızla paylaşmanız kolaylaşır. “Ama ben bunu zaten biliyorum, her zaman aynı şeyi yapıyorum” tuzağına düşmeyin. Bir gün o sunucuyu başkası yönetecek, ya da siz başka bir şirkette bunu tekrar kuracaksınız. Hazır scriptleriniz olsun.
IIS’e özel bir sorunuz varsa yorumlarda paylaşın, elimden geldiğince yardımcı olmaya çalışayım.