Disk yönetimi konusunda sysadmin’lerin en çok zaman harcadığı işlerin başında depolama alanı takibi, disk bölümlendirme ve performans izleme geliyor. Windows Server ortamlarında GUI üzerinden bu işleri yapmak mümkün, ancak onlarca sunucuyu yönetiyorsanız bu yaklaşım sizi yorar. PowerShell ile disk yönetimini öğrendiğinizde, hem zaman kazanırsınız hem de tutarlı, tekrarlanabilir işlemler yapabilirsiniz. Bu yazıda gerçek dünya senaryoları üzerinden PowerShell ile disk ve depolama yönetimini ele alacağız.
Disk Bilgilerini Sorgulamak
Her şeyden önce sistemdeki disklerin durumunu görmek gerekiyor. Get-Disk cmdlet’i bu iş için temel araçtır.
# Tüm diskleri listele
Get-Disk
# Belirli bir disk hakkında detaylı bilgi
Get-Disk -Number 0 | Select-Object *
# Sadece offline diskleri bul
Get-Disk | Where-Object {$_.OperationalStatus -eq "Offline"}
# Disk boyutunu GB cinsinden göster
Get-Disk | Select-Object Number, FriendlyName,
@{Name="Size(GB)";Expression={[math]::Round($_.Size/1GB,2)}},
OperationalStatus, PartitionStyle
Bu komutun çıktısında dikkat etmeniz gereken alanlar şunlar:
- PartitionStyle: MBR ya da GPT olduğunu gösterir, 2 TB üzeri diskler için GPT zorunludur
- OperationalStatus: Online, Offline, Unknown gibi değerler alır
- IsReadOnly: True ise disk yazma korumalıdır
- IsBoot: Sistemin boot diskini gösterir
Pratik bir senaryo düşünelim. Yeni bir fiziksel sunucu kurulumu yaptınız ve depolama ekibinden 5 adet disk eklendi. Bunların hepsinin düzgün tanınıp tanınmadığını kontrol etmeniz gerekiyor.
# Yeni eklenen ve henüz initialize edilmemiş diskleri bul
$rawDisks = Get-Disk | Where-Object {$_.PartitionStyle -eq "RAW"}
$rawDisks | Select-Object Number, FriendlyName,
@{Name="Size(GB)";Expression={[math]::Round($_.Size/1GB,2)}}
# Kaç adet ham disk var?
Write-Host "Toplam initialize edilmemiş disk sayısı: $($rawDisks.Count)" -ForegroundColor Yellow
Disk Partition ve Volume İşlemleri
Diskleri buldunuz, şimdi bunları kullanılabilir hale getirmeniz gerekiyor. Bu adımda Initialize, Partition ve Format işlemlerini sırasıyla yapacaksınız.
# Tek bir disk için tam kurulum süreci
# Disk 1'i GPT olarak initialize et
Initialize-Disk -Number 1 -PartitionStyle GPT -PassThru
# Tüm alanı kaplayan bir partition oluştur
New-Partition -DiskNumber 1 -UseMaximumSize -AssignDriveLetter
# Partition'ı NTFS olarak formatla
$partition = Get-Partition -DiskNumber 1 | Where-Object {$_.Type -eq "Basic"}
Format-Volume -DriveLetter $partition.DriveLetter -FileSystem NTFS `
-NewFileSystemLabel "DataDisk01" -Confirm:$false
Birden fazla diski aynı anda işlemeniz gerektiğinde döngü kullanmak hayat kurtarır. Diyelim ki 5 adet veri diskini hızlıca kurmanız gerekiyor.
# Tüm RAW diskleri otomatik olarak kur
$diskCounter = 1
Get-Disk | Where-Object {$_.PartitionStyle -eq "RAW"} | ForEach-Object {
$diskNumber = $_.Number
Write-Host "Disk $diskNumber işleniyor..." -ForegroundColor Cyan
# Initialize
Initialize-Disk -Number $diskNumber -PartitionStyle GPT -PassThru | Out-Null
# Partition oluştur
$newPartition = New-Partition -DiskNumber $diskNumber -UseMaximumSize -AssignDriveLetter
# Formatla
Format-Volume -DriveLetter $newPartition.DriveLetter `
-FileSystem NTFS `
-NewFileSystemLabel "DataDisk0$diskCounter" `
-Confirm:$false | Out-Null
Write-Host "Disk $diskNumber tamamlandi. Surucu harfi: $($newPartition.DriveLetter)" `
-ForegroundColor Green
$diskCounter++
}
Disk Alanı İzleme ve Raporlama
Sysadmin hayatında en çok gelen ticket türlerinden biri “disk doldu” bildirimleridir. Bu duruma reaktif değil proaktif yaklaşmak gerekiyor.
# Tüm sürücülerin doluluk oranını göster
Get-PSDrive -PSProvider FileSystem |
Where-Object {$_.Used -gt 0} |
Select-Object Name,
@{Name="Total(GB)";Expression={[math]::Round(($_.Used + $_.Free)/1GB,2)}},
@{Name="Used(GB)";Expression={[math]::Round($_.Used/1GB,2)}},
@{Name="Free(GB)";Expression={[math]::Round($_.Free/1GB,2)}},
@{Name="Used%";Expression={[math]::Round(($_.Used/($_.Used+$_.Free))*100,1)}} |
Sort-Object "Used%" -Descending
Burada güzel bir uyarı mekanizması kurabilirsiniz. Kritik eşiği aşan diskleri tespit edip mail atması için basit bir script yazalım.
# Disk doluluk uyarı scripti
$threshold = 85 # Yüzde olarak uyarı eşiği
$criticalThreshold = 95 # Kritik eşik
$serverName = $env:COMPUTERNAME
$alerts = @()
Get-PSDrive -PSProvider FileSystem |
Where-Object {$_.Used -gt 0} |
ForEach-Object {
$totalSize = $_.Used + $_.Free
if ($totalSize -gt 0) {
$usedPercent = [math]::Round(($_.Used / $totalSize) * 100, 1)
$freeGB = [math]::Round($_.Free / 1GB, 2)
if ($usedPercent -ge $criticalThreshold) {
$alerts += [PSCustomObject]@{
Server = $serverName
Drive = $_.Name
UsedPct = $usedPercent
FreeGB = $freeGB
Severity = "KRITIK"
}
Write-Host "KRITIK: $serverName - $($_.Name): dizin %$usedPercent dolu!" `
-ForegroundColor Red
}
elseif ($usedPercent -ge $threshold) {
$alerts += [PSCustomObject]@{
Server = $serverName
Drive = $_.Name
UsedPct = $usedPercent
FreeGB = $freeGB
Severity = "UYARI"
}
Write-Host "UYARI: $serverName - $($_.Name): dizin %$usedPercent dolu!" `
-ForegroundColor Yellow
}
}
}
# Uyarı varsa e-posta gönder
if ($alerts.Count -gt 0) {
$body = $alerts | ConvertTo-Html -Fragment | Out-String
Send-MailMessage -To "[email protected]" `
-From "[email protected]" `
-Subject "[$serverName] Disk Doluluk Uyarisi" `
-Body $body -BodyAsHtml `
-SmtpServer "smtp.sirket.com"
Write-Host "Uyari maili gonderildi." -ForegroundColor Cyan
}
Bu scripti Task Scheduler ile her gece çalıştırırsanız, sabah işe geldiğinizde sorunlu diskler mail kutunuzda sizi bekliyor olur.
WMI ile Daha Derin Disk Analizi
Get-Disk ve Get-PSDrive cmdlet’leri çoğu iş için yeterli, ancak daha detaylı bilgiye ihtiyaç duyduğunuzda WMI sorgularına başvurmanız gerekiyor. Özellikle uzak sunuculardan bilgi toplarken WMI çok kullanışlı.
# Yerel ve uzak sunucularda disk bilgisi topla
$servers = @("Server01", "Server02", "Server03")
$results = foreach ($server in $servers) {
try {
$disks = Get-WmiObject -Class Win32_LogicalDisk `
-ComputerName $server `
-Filter "DriveType=3" `
-ErrorAction Stop
foreach ($disk in $disks) {
[PSCustomObject]@{
Sunucu = $server
Surucu = $disk.DeviceID
"Toplam GB" = [math]::Round($disk.Size / 1GB, 2)
"Bos GB" = [math]::Round($disk.FreeSpace / 1GB, 2)
"Dolu %" = [math]::Round((($disk.Size - $disk.FreeSpace) / $disk.Size) * 100, 1)
Durum = if (($disk.FreeSpace / $disk.Size * 100) -lt 15) { "KRITIK" }
elseif (($disk.FreeSpace / $disk.Size * 100) -lt 25) { "UYARI" }
else { "NORMAL" }
}
}
}
catch {
Write-Warning "$server sunucusuna erisilemedi: $_"
}
}
# Sonuçları ekrana yazdır
$results | Sort-Object Sunucu, Surucu
# CSV olarak kaydet
$results | Export-Csv -Path "C:ReportsDiskReport_$(Get-Date -Format 'yyyyMMdd').csv" `
-NoTypeInformation -Encoding UTF8
Volume Shadow Copy (VSS) Yönetimi
Yedekleme altyapısının önemli bir parçası olan VSS’i PowerShell ile yönetmek oldukça pratik. Özellikle VSS snapshot’larının ne kadar yer kapladığını ve ne zaman oluşturulduğunu takip etmek önemli.
# Mevcut shadow copy'leri listele
Get-WmiObject Win32_ShadowCopy |
Select-Object ID,
VolumeName,
@{Name="OlusturmaTarihi";Expression={
[Management.ManagementDateTimeConverter]::ToDateTime($_.InstallDate)
}},
@{Name="Boyut(GB)";Expression={[math]::Round($_.Count/1GB,2)}}
# Belirli bir sürücü için shadow copy oluştur
$volume = (Get-Volume -DriveLetter C).Path
$shadowClass = [WMICLASS]"rootcimv2:win32_shadowcopy"
$result = $shadowClass.Create($volume, "ClientAccessible")
if ($result.ReturnValue -eq 0) {
Write-Host "Shadow copy basariyla olusturuldu. ID: $($result.ShadowID)" -ForegroundColor Green
} else {
Write-Host "Shadow copy olusturulamadi. Hata kodu: $($result.ReturnValue)" -ForegroundColor Red
}
Storage Pool ve Depolama Havuzu Yönetimi
Windows Server 2012 ve sonrasında gelen Storage Spaces özelliği, birden fazla fiziksel diski tek bir mantıksal havuzda birleştirmenizi sağlıyor. PowerShell bu özelliği yönetmek için ideal araç.
# Mevcut storage pool'ları listele
Get-StoragePool | Select-Object FriendlyName, OperationalStatus,
@{Name="Toplam(GB)";Expression={[math]::Round($_.Size/1GB,2)}},
@{Name="Ayrilan(GB)";Expression={[math]::Round($_.AllocatedSize/1GB,2)}}
# Storage pool için uygun fiziksel diskleri bul
Get-PhysicalDisk -CanPool $true |
Select-Object FriendlyName, Size, MediaType, OperationalStatus
# Yeni storage pool oluştur (örnek)
$physicalDisks = Get-PhysicalDisk -CanPool $true | Select-Object -First 3
New-StoragePool -FriendlyName "DataPool01" `
-StorageSubSystemFriendlyName (Get-StorageSubSystem).FriendlyName `
-PhysicalDisks $physicalDisks
# Pool üzerinde RAID-like yapılandırma (Mirror)
New-VirtualDisk -StoragePoolFriendlyName "DataPool01" `
-FriendlyName "DataVDisk01" `
-ResiliencySettingName Mirror `
-Size 500GB `
-ProvisioningType Thin
# Virtual disk'i kullanılabilir hale getir
Get-VirtualDisk -FriendlyName "DataVDisk01" |
Get-Disk |
Initialize-Disk -PartitionStyle GPT -PassThru |
New-Partition -UseMaximumSize -AssignDriveLetter |
Format-Volume -FileSystem NTFS -NewFileSystemLabel "DataVol01" -Confirm:$false
Disk Performans Metrikleri
Disk doluluk takibinin yanı sıra performans izleme de kritik öneme sahip. Özellikle SQL Server veya yoğun I/O yapan uygulamaların çalıştığı sunucularda disk latency ve throughput değerlerini takip etmek gerekiyor.
# Disk performans verilerini topla
$diskCounters = Get-Counter -Counter @(
"PhysicalDisk(*)Avg. Disk sec/Read",
"PhysicalDisk(*)Avg. Disk sec/Write",
"PhysicalDisk(*)Disk Reads/sec",
"PhysicalDisk(*)Disk Writes/sec",
"PhysicalDisk(*)% Disk Time"
) -SampleInterval 2 -MaxSamples 5
$diskCounters.CounterSamples |
Where-Object {$_.InstanceName -ne "_total"} |
Select-Object InstanceName,
@{Name="Counter";Expression={($_.Path -split "\")[-1]}},
@{Name="Value";Expression={[math]::Round($_.CookedValue, 4)}} |
Sort-Object InstanceName, Counter
Bir üretim ortamında gördüğüm klasik bir senaryoyu paylaşayım. SQL Server’ın yavaş çalıştığından şikayet geliyordu. Aşağıdaki script ile 5 dakika boyunca disk metriklerini kaydettik ve sorunun log diskindeki yüksek write latency’den kaynaklandığını bulduk.
# 5 dakika boyunca disk latency takibi ve rapor
$samples = @()
$monitorDuration = 300 # saniye
$interval = 10 # saniye
$iterations = $monitorDuration / $interval
Write-Host "Disk performans izleme basliyor ($monitorDuration saniye)..." -ForegroundColor Cyan
for ($i = 1; $i -le $iterations; $i++) {
$timestamp = Get-Date
$counters = Get-Counter -Counter @(
"PhysicalDisk(*)Avg. Disk sec/Read",
"PhysicalDisk(*)Avg. Disk sec/Write"
) -ErrorAction SilentlyContinue
$counters.CounterSamples |
Where-Object {$_.InstanceName -ne "_total"} |
ForEach-Object {
$samples += [PSCustomObject]@{
Zaman = $timestamp
Disk = $_.InstanceName
Metrik = ($_.Path -split "\")[-1]
Deger_ms = [math]::Round($_.CookedValue * 1000, 2)
}
}
Write-Progress -Activity "Performans verisi toplaniyor" `
-PercentComplete (($i / $iterations) * 100) `
-Status "$i / $iterations iterasyon tamamlandi"
if ($i -lt $iterations) { Start-Sleep -Seconds $interval }
}
# Yüksek latency olan disk/periyotları bul
Write-Host "`nYuksek Latency Olaylari (>20ms):" -ForegroundColor Yellow
$samples | Where-Object {$_.Deger_ms -gt 20} |
Sort-Object Deger_ms -Descending |
Select-Object -First 20
# Özet rapor
Write-Host "`nOrtalama Latency Ozeti:" -ForegroundColor Cyan
$samples | Group-Object Disk, Metrik | ForEach-Object {
[PSCustomObject]@{
Disk = ($_.Name -split ", ")[0]
Metrik = ($_.Name -split ", ")[1]
"Ort(ms)" = [math]::Round(($_.Group.Deger_ms | Measure-Object -Average).Average, 2)
"Maks(ms)" = [math]::Round(($_.Group.Deger_ms | Measure-Object -Maximum).Maximum, 2)
}
} | Sort-Object "Maks(ms)" -Descending
Büyük Dosyaları Bulma ve Temizlik
Disk doluluk sorunlarının büyük kısmı gereksiz büyük dosyalardan kaynaklanır. PowerShell ile bunları hızlıca tespit edebilirsiniz.
# Belirli bir dizindeki en büyük dosyaları bul
function Get-LargeFiles {
param(
[string]$Path = "C:",
[int]$TopCount = 20,
[int]$MinSizeMB = 100
)
Write-Host "Taranıyor: $Path (Bu işlem biraz sürebilir...)" -ForegroundColor Cyan
Get-ChildItem -Path $Path -Recurse -File -ErrorAction SilentlyContinue |
Where-Object {$_.Length -gt ($MinSizeMB * 1MB)} |
Sort-Object Length -Descending |
Select-Object -First $TopCount |
Select-Object FullName,
@{Name="Boyut(MB)";Expression={[math]::Round($_.Length/1MB,2)}},
LastWriteTime,
@{Name="Uzanti";Expression={$_.Extension}}
}
# Kullanım örneği
Get-LargeFiles -Path "D:" -TopCount 30 -MinSizeMB 500
# Windows temp dosyalarını temizle
function Clear-TempFiles {
$tempPaths = @(
$env:TEMP,
"C:WindowsTemp",
"C:WindowsSoftwareDistributionDownload"
)
foreach ($path in $tempPaths) {
if (Test-Path $path) {
$before = (Get-ChildItem $path -Recurse -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
Get-ChildItem $path -Recurse -ErrorAction SilentlyContinue |
Remove-Item -Force -Recurse -ErrorAction SilentlyContinue
$after = (Get-ChildItem $path -Recurse -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
$freed = [math]::Round(($before - $after) / 1MB, 2)
Write-Host "$path temizlendi. Kazanilan alan: $freed MB" -ForegroundColor Green
}
}
}
Disk Sağlığı ve SMART Verisi
Fiziksel disk sağlığını izlemek için SMART verilerine bakmak gerekiyor. PowerShell ile bu verilere de erişebilirsiniz.
# Disk sağlık durumunu kontrol et
Get-PhysicalDisk | Select-Object FriendlyName,
MediaType,
OperationalStatus,
HealthStatus,
@{Name="Boyut(GB)";Expression={[math]::Round($_.Size/1GB,2)}}
# Sorunlu diskleri bul
$unhealthyDisks = Get-PhysicalDisk |
Where-Object {$_.HealthStatus -ne "Healthy" -or $_.OperationalStatus -ne "OK"}
if ($unhealthyDisks) {
Write-Host "UYARI: Sagliksiz disk tespit edildi!" -ForegroundColor Red
$unhealthyDisks | Select-Object FriendlyName, HealthStatus, OperationalStatus
} else {
Write-Host "Tüm diskler saglikli." -ForegroundColor Green
}
# Storage reliability counter (NVMe ve bazı SSD'ler için)
Get-StorageReliabilityCounter -PhysicalDisk (Get-PhysicalDisk) |
Select-Object DeviceId,
ReadErrorsTotal,
WriteErrorsTotal,
Temperature,
Wear |
Sort-Object Wear -Descending
Düzenli Bakım için Scheduled Script
Tüm bu işlemleri bir araya getiren ve düzenli çalışacak şekilde ayarlayabileceğiniz kapsamlı bir script:
# Haftalık disk bakım ve raporlama scripti
# Task Scheduler ile her Pazartesi 06:00'da çalıştırın
$reportDate = Get-Date -Format "yyyy-MM-dd"
$reportPath = "C:ReportsDiskReport_$reportDate.html"
$serverName = $env:COMPUTERNAME
# HTML rapor başlığı
$htmlHeader = @"
<html><head><style>
body { font-family: Arial; margin: 20px; }
h2 { color: #336699; }
.kritik { background-color: #ff4444; color: white; padding: 3px; }
.uyari { background-color: #ffbb33; padding: 3px; }
.normal { background-color: #00C851; color: white; padding: 3px; }
</style></head><body>
<h2>$serverName - Disk Durum Raporu - $reportDate</h2>
"@
# Disk doluluk bilgisi
$diskInfo = Get-PSDrive -PSProvider FileSystem |
Where-Object {$_.Used -gt 0} |
Select-Object Name,
@{Name="Toplam(GB)";Expression={[math]::Round(($_.Used+$_.Free)/1GB,2)}},
@{Name="Kullanilan(GB)";Expression={[math]::Round($_.Used/1GB,2)}},
@{Name="Bos(GB)";Expression={[math]::Round($_.Free/1GB,2)}},
@{Name="Dolu%";Expression={[math]::Round(($_.Used/($_.Used+$_.Free))*100,1)}}
$diskHtml = $diskInfo | ConvertTo-Html -Fragment -PreContent "<h3>Disk Doluluk Durumu</h3>"
# Disk sağlığı
$healthHtml = Get-PhysicalDisk |
Select-Object FriendlyName, HealthStatus, OperationalStatus |
ConvertTo-Html -Fragment -PreContent "<h3>Fiziksel Disk Sagligi</h3>"
# Raporu kaydet
$htmlContent = $htmlHeader + $diskHtml + $healthHtml + "</body></html>"
$htmlContent | Out-File -FilePath $reportPath -Encoding UTF8
Write-Host "Rapor olusturuldu: $reportPath" -ForegroundColor Green
# E-posta ile gönder
$criticalDrives = $diskInfo | Where-Object {$_."Dolu%" -ge 90}
$subject = if ($criticalDrives) {
"[KRITIK] $serverName Disk Raporu - $reportDate"
} else {
"$serverName Disk Raporu - $reportDate"
}
Send-MailMessage -To "[email protected]" `
-From "[email protected]" `
-Subject $subject `
-Body (Get-Content $reportPath -Raw) `
-BodyAsHtml `
-SmtpServer "smtp.sirket.com" `
-Attachments $reportPath
Sonuç
PowerShell ile disk yönetimi, başlangıçta karmaşık görünse de öğrendikten sonra sysadmin hayatınızı ciddi ölçüde kolaylaştırıyor. Bu yazıda ele aldığımız konuları özetlemek gerekirse:
- Disk ve partition yönetimi için
Get-Disk,New-Partition,Format-Volumecmdlet’lerini kullanın - Disk doluluk takibini otomatize edin, reaktif değil proaktif olun
- Uzak sunucularda toplu bilgi toplama için WMI sorgularından yararlanın
- Storage Spaces özelliğini PowerShell üzerinden yönetmek ciddi esneklik sağlıyor
- Disk performans metriklerini özellikle yoğun I/O uygulamaları için düzenli izleyin
- Haftalık otomatik raporlar oluşturun ve mail ile gönderin
Buradaki scriptleri olduğu gibi kopyalayıp yapıştırmak yerine kendi ortamınıza uyarlayın. Mail sunucusu adresleri, eşik değerleri ve rapor yolları gibi parametreleri mutlaka değiştirin. Scriptleri production’a almadan önce test ortamında çalıştırmanızı da öneririm. Disk işlemleri geri alınamaz olabilir, bu yüzden özellikle partition ve format işlemlerinde dikkatli olun.