PowerShell ile Sistem Bilgisi ve Donanım Raporu Alma
Bir Windows Server ortamında çalışırken en sık karşılaşılan durumlardan biri şudur: “Bu sunucunun RAM’i kaç GB’tı? Hangi işlemci var? Disk alanı ne durumda?” Özellikle birden fazla sunucu yönetiyorsanız bu soruların cevabını her seferinde RDP açıp manuel kontrol ederek bulmak hem zaman kaybıdır hem de hata yapmaya açık bir süreçtir. PowerShell tam da bu noktada devreye giriyor ve size hem anlık sorgu hem de otomatik raporlama imkanı sunuyor.
Bu yazıda PowerShell kullanarak sistem ve donanım bilgilerini nasıl toplayacağınızı, bu bilgileri nasıl raporlayacağınızı ve bunu birden fazla sunucuya nasıl ölçekleyeceğinizi ele alacağız. Ister tek bir iş istasyonu, ister 50 sunucudan oluşan bir farm olsun, buradaki teknikler işinizi görecek.
Temel Sistem Bilgisi Komutları
Önce en basit ve en sık kullanılan komutlardan başlayalım. PowerShell’de sistem bilgisi almanın birkaç farklı yolu var ama Get-ComputerInfo cmdlet’i bu işin en temiz ve kapsamlı çözümü.
# Temel sistem bilgisi
Get-ComputerInfo
# Sadece belirli özellikleri çek
Get-ComputerInfo -Property CsName, OsName, OsVersion, CsProcessors, CsTotalPhysicalMemory
Bu komut çok fazla bilgi döndürür, genellikle ihtiyacınız olanı filtrelemek daha mantıklıdır. Ama bazen tüm çıktıyı bir değişkene alıp sonra dilediğiniz gibi işlemek daha esnek bir yaklaşım sunar.
# Bilgileri değişkene al ve belirli alanları göster
$sysInfo = Get-ComputerInfo
Write-Host "Bilgisayar Adı: $($sysInfo.CsName)"
Write-Host "İşletim Sistemi: $($sysInfo.OsName)"
Write-Host "OS Versiyonu: $($sysInfo.OsVersion)"
Write-Host "Toplam RAM: $([math]::Round($sysInfo.CsTotalPhysicalMemory / 1GB, 2)) GB"
Write-Host "Son Başlatma: $($sysInfo.OsLastBootUpTime)"
Get-ComputerInfo Windows 10 ve Server 2016 ile birlikte geldi. Eğer daha eski sistemlerle çalışıyorsanız WMI sorgularına başvurmanız gerekecek, bunu da birazdan ele alacağız.
İşlemci Bilgisi
CPU hakkında detaylı bilgi almak için Get-WmiObject veya modern alternatifi Get-CimInstance kullanabilirsiniz. Ben artık her yerde Get-CimInstance tercih ediyorum çünkü hem daha hızlı hem de HTTPS üzerinden uzak bağlantı yapabilmek gibi avantajları var.
# İşlemci bilgisi
Get-CimInstance -ClassName Win32_Processor | Select-Object `
Name,
NumberOfCores,
NumberOfLogicalProcessors,
MaxClockSpeed,
CurrentClockSpeed,
L2CacheSize,
L3CacheSize,
Manufacturer
# Çoklu işlemci varsa her birini göster
$cpuList = Get-CimInstance -ClassName Win32_Processor
foreach ($cpu in $cpuList) {
Write-Host "CPU: $($cpu.Name)"
Write-Host "Çekirdek Sayısı: $($cpu.NumberOfCores)"
Write-Host "Mantıksal İşlemci: $($cpu.NumberOfLogicalProcessors)"
Write-Host "Max Frekans: $($cpu.MaxClockSpeed) MHz"
Write-Host "---"
}
Sunucular söz konusu olduğunda çift soketli sistemler oldukça yaygın. Bu komut her iki işlemciyi de ayrı ayrı listeler, dolayısıyla “Bu sunucuda 2x Xeon mu var?” sorusuna kolayca cevap bulursunuz.
RAM Bilgisi ve DIMM Detayları
Toplam RAM miktarını öğrenmek kolay, ama hangi slotlara kaç GB’lık modüller takılı bunu öğrenmek bazen çok daha değerli. Özellikle RAM yükseltmesi planlarken boş slot var mı, varsa maksimum kaç GB destekliyor gibi soruların cevabı kritik olur.
# Toplam fiziksel RAM
$os = Get-CimInstance -ClassName Win32_OperatingSystem
$totalRAM = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2)
$freeRAM = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
$usedRAM = $totalRAM - $freeRAM
Write-Host "Toplam RAM: $totalRAM GB"
Write-Host "Kullanılan RAM: $usedRAM GB"
Write-Host "Boş RAM: $freeRAM GB"
Write-Host "RAM Kullanım Oranı: $([math]::Round(($usedRAM/$totalRAM)*100, 1))%"
# DIMM slot detayları
Get-CimInstance -ClassName Win32_PhysicalMemory | Select-Object `
BankLabel,
DeviceLocator,
Capacity,
Speed,
Manufacturer,
PartNumber | ForEach-Object {
$_.Capacity = "$([math]::Round($_.Capacity / 1GB, 0)) GB"
$_
}
Gerçek dünyadan bir örnek vereyim: Bir müşterinin sunucusunda RAM yetersizliği şikayeti vardı. Yukarıdaki komutu çalıştırdığımda 4 slotun 2’sinde 8 GB’lık modül olduğunu, diğer 2 slotun boş olduğunu gördüm. 16 GB RAM’li sistem aslında 32 GB’a çıkarılabilirdi ve bu bilgiye 30 saniyede ulaştım.
Disk ve Depolama Bilgisi
Disk bilgisi en sık ihtiyaç duyulan konulardan biri. Hem fiziksel disklerin durumu hem de mantıksal birimlerin doluluk oranı önemli.
# Mantıksal disk bilgisi (sürücü harfleri ile)
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" | ForEach-Object {
$totalGB = [math]::Round($_.Size / 1GB, 2)
$freeGB = [math]::Round($_.FreeSpace / 1GB, 2)
$usedGB = $totalGB - $freeGB
$usedPercent = [math]::Round(($usedGB / $totalGB) * 100, 1)
$status = if ($usedPercent -gt 90) { "KRITIK" }
elseif ($usedPercent -gt 75) { "UYARI" }
else { "NORMAL" }
Write-Host "Sürücü: $($_.DeviceID)"
Write-Host " Toplam: $totalGB GB"
Write-Host " Kullanılan: $usedGB GB ($usedPercent%)"
Write-Host " Boş: $freeGB GB"
Write-Host " Durum: $status"
Write-Host ""
}
Bu scriptte pratik bir detay var: Disk doluluk yüzdesine göre otomatik durum ataması yapıyoruz. %90 üzeri KRITIK, %75 üzeri UYARI. Bu eşik değerleri kendi ortamınıza göre ayarlayabilirsiniz.
# Fiziksel disk bilgisi
Get-CimInstance -ClassName Win32_DiskDrive | Select-Object `
Model,
MediaType,
Size,
Status,
InterfaceType,
SerialNumber | ForEach-Object {
$sizeGB = [math]::Round($_.Size / 1GB, 0)
Write-Host "Model: $($_.Model)"
Write-Host "Tür: $($_.MediaType)"
Write-Host "Boyut: $sizeGB GB"
Write-Host "Arayüz: $($_.InterfaceType)"
Write-Host "Durum: $($_.Status)"
Write-Host "Seri No: $($_.SerialNumber)"
Write-Host "---"
}
Ağ Adaptörü ve IP Bilgisi
Ağ konfigürasyonu bilgileri de raporun önemli bir parçası. Hangi adaptörler aktif, IP adresleri ne, DNS ve gateway ayarları doğru mu?
# Aktif ağ adaptörleri ve IP bilgileri
Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled=True" | ForEach-Object {
Write-Host "Adaptör: $($_.Description)"
Write-Host "IP Adresi: $($_.IPAddress -join ', ')"
Write-Host "Subnet Mask: $($_.IPSubnet -join ', ')"
Write-Host "Default Gateway: $($_.DefaultIPGateway -join ', ')"
Write-Host "DNS Sunucuları: $($_.DNSServerSearchOrder -join ', ')"
Write-Host "MAC Adresi: $($_.MACAddress)"
Write-Host "DHCP Aktif: $($_.DHCPEnabled)"
Write-Host ""
}
BIOS ve Anakart Bilgisi
Özellikle fiziksel sunucularda BIOS versiyonu ve anakart bilgisi bakım ve firmware güncellemeleri açısından önemlidir.
# BIOS bilgisi
$bios = Get-CimInstance -ClassName Win32_BIOS
Write-Host "BIOS Üreticisi: $($bios.Manufacturer)"
Write-Host "BIOS Versiyonu: $($bios.SMBIOSBIOSVersion)"
Write-Host "BIOS Tarihi: $($bios.ReleaseDate)"
Write-Host "Seri Numarası: $($bios.SerialNumber)"
# Anakart bilgisi
$board = Get-CimInstance -ClassName Win32_BaseBoard
Write-Host ""
Write-Host "Anakart Üreticisi: $($board.Manufacturer)"
Write-Host "Anakart Modeli: $($board.Product)"
Write-Host "Anakart Seri No: $($board.SerialNumber)"
# Sistem kasa/chassis bilgisi
$chassis = Get-CimInstance -ClassName Win32_SystemEnclosure
Write-Host ""
Write-Host "Kasa Tipi: $($chassis.ChassisTypes)"
Write-Host "Üretici: $($chassis.Manufacturer)"
Kapsamlı Donanım Raporu Script’i
Şimdiye kadar öğrendiklerimizi bir araya getirelim ve tam anlamıyla kullanılabilir bir rapor üretelim. Bu script çalıştığında HTML formatında güzel bir rapor dosyası oluşturuyor.
# Kapsamlı sistem raporu oluştur
function Get-SystemReport {
param(
[string]$OutputPath = "C:ReportsSystemReport_$(Get-Date -Format 'yyyyMMdd_HHmmss').html",
[string]$ComputerName = $env:COMPUTERNAME
)
# Rapor dizinini oluştur
$reportDir = Split-Path $OutputPath -Parent
if (-not (Test-Path $reportDir)) {
New-Item -ItemType Directory -Path $reportDir -Force | Out-Null
}
Write-Host "Sistem bilgileri toplanıyor: $ComputerName" -ForegroundColor Cyan
# Veri toplama
$sysInfo = Get-ComputerInfo
$cpuInfo = Get-CimInstance -ClassName Win32_Processor
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
$diskInfo = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3"
$ramInfo = Get-CimInstance -ClassName Win32_PhysicalMemory
$netInfo = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled=True"
$biosInfo = Get-CimInstance -ClassName Win32_BIOS
$boardInfo = Get-CimInstance -ClassName Win32_BaseBoard
# Uptime hesapla
$uptime = (Get-Date) - $osInfo.LastBootUpTime
$uptimeStr = "{0} gün, {1} saat, {2} dakika" -f $uptime.Days, $uptime.Hours, $uptime.Minutes
# RAM özeti
$totalRAM = [math]::Round(($ramInfo | Measure-Object -Property Capacity -Sum).Sum / 1GB, 0)
$freeRAM = [math]::Round($osInfo.FreePhysicalMemory / 1MB, 1)
# HTML rapor içeriği oluştur
$htmlContent = @"
<!DOCTYPE html>
<html lang='tr'>
<head>
<meta charset='UTF-8'>
<title>Sistem Raporu - $ComputerName</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; background-color: #f5f5f5; }
h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
h2 { color: #34495e; background-color: #ecf0f1; padding: 8px; border-left: 4px solid #3498db; }
.info-block { background-color: white; padding: 15px; margin: 10px 0; border-radius: 5px; box-shadow: 1px 1px 3px rgba(0,0,0,0.1); }
.label { font-weight: bold; color: #555; min-width: 200px; display: inline-block; }
.value { color: #2c3e50; }
.warning { color: #e67e22; font-weight: bold; }
.critical { color: #e74c3c; font-weight: bold; }
.ok { color: #27ae60; font-weight: bold; }
.report-date { color: #7f8c8d; font-size: 0.9em; }
</style>
</head>
<body>
<h1>Sistem Donanım Raporu: $ComputerName</h1>
<p class='report-date'>Rapor Tarihi: $(Get-Date -Format 'dd.MM.yyyy HH:mm:ss')</p>
<h2>Genel Sistem Bilgisi</h2>
<div class='info-block'>
<p><span class='label'>Bilgisayar Adı:</span> <span class='value'>$($sysInfo.CsName)</span></p>
<p><span class='label'>İşletim Sistemi:</span> <span class='value'>$($sysInfo.OsName)</span></p>
<p><span class='label'>OS Versiyonu:</span> <span class='value'>$($sysInfo.OsVersion)</span></p>
<p><span class='label'>Sistem Çalışma Süresi:</span> <span class='value'>$uptimeStr</span></p>
<p><span class='label'>Son Başlatma:</span> <span class='value'>$($osInfo.LastBootUpTime)</span></p>
</div>
<h2>İşlemci Bilgisi</h2>
<div class='info-block'>
$(foreach ($cpu in $cpuInfo) {
"<p><span class='label'>CPU:</span> <span class='value'>$($cpu.Name)</span></p>"
"<p><span class='label'>Çekirdek / Mantıksal:</span> <span class='value'>$($cpu.NumberOfCores) / $($cpu.NumberOfLogicalProcessors)</span></p>"
"<p><span class='label'>Max Frekans:</span> <span class='value'>$($cpu.MaxClockSpeed) MHz</span></p>"
})
</div>
</body>
</html>
"@
$htmlContent | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "Rapor oluşturuldu: $OutputPath" -ForegroundColor Green
return $OutputPath
}
# Fonksiyonu çalıştır
Get-SystemReport -OutputPath "C:ReportsSunucuRaporu.html"
Uzak Sunucularda Toplu Rapor Alma
Gerçek ortamlarda onlarca sunucu yönetiyorsunuz. Tek tek bağlanmak yerine PowerShell Remoting ile tüm sunuculardan aynı anda bilgi toplayabilirsiniz.
# Birden fazla sunucudan bilgi toplama
$serverList = @("SRV-DC01", "SRV-FILE01", "SRV-SQL01", "SRV-WEB01")
$results = Invoke-Command -ComputerName $serverList -ScriptBlock {
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
$cpuInfo = Get-CimInstance -ClassName Win32_Processor | Select-Object -First 1
$diskC = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='C:'"
$totalRAM = [math]::Round($osInfo.TotalVisibleMemorySize / 1MB, 1)
$freeRAM = [math]::Round($osInfo.FreePhysicalMemory / 1MB, 1)
$diskTotal = [math]::Round($diskC.Size / 1GB, 1)
$diskFree = [math]::Round($diskC.FreeSpace / 1GB, 1)
[PSCustomObject]@{
Sunucu = $env:COMPUTERNAME
OS = $osInfo.Caption
CPU = $cpuInfo.Name
ToplamRAM_GB = $totalRAM
BosRAM_GB = $freeRAM
CDisktoplam_GB = $diskTotal
CDiskBos_GB = $diskFree
CDiskDoluluk = "$([math]::Round((($diskTotal - $diskFree)/$diskTotal)*100,1))%"
SonBaslatma = $osInfo.LastBootUpTime
}
} -ErrorAction SilentlyContinue
# Sonuçları ekranda göster
$results | Sort-Object Sunucu | Format-List
# CSV olarak kaydet
$results | Export-Csv -Path "C:ReportsTumSunucular_$(Get-Date -Format 'yyyyMMdd').csv" `
-Encoding UTF8 -NoTypeInformation
Write-Host "Rapor kaydedildi." -ForegroundColor Green
Bu yaklaşımda birkaç önemli nokta var. Invoke-Command ile parallel çalışma yapıldığı için tüm sunuculardan aynı anda veri toplanır, 20 sunucu için bile ciddi bir zaman kazancı sağlar. -ErrorAction SilentlyContinue ile erişilemeyen sunucular scripti durdurmaz, sadece atlanır.
Zamanlı Rapor ve E-posta Gönderimi
Bu scripti Task Scheduler ile her sabah çalıştırıp sonuçları e-posta ile almak harika bir monitoring çözümü oluşturur.
# Haftalık donanım raporu ve e-posta gönderimi
function Send-HardwareReport {
param(
[string[]]$Servers,
[string]$SmtpServer = "mail.sirket.local",
[string]$From = "[email protected]",
[string[]]$To = @("[email protected]"),
[int]$SmtpPort = 25
)
$reportDate = Get-Date -Format "dd.MM.yyyy"
$subject = "Haftalık Donanım Raporu - $reportDate"
# Verileri topla
$reportData = @()
foreach ($server in $Servers) {
try {
$data = Invoke-Command -ComputerName $server -ScriptBlock {
$os = Get-CimInstance Win32_OperatingSystem
$disks = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3"
$diskAlerts = $disks | Where-Object {
($_.Size - $_.FreeSpace) / $_.Size * 100 -gt 80
} | ForEach-Object { "$($_.DeviceID) %$([math]::Round(($_.Size-$_.FreeSpace)/$_.Size*100,0)) dolu" }
[PSCustomObject]@{
Sunucu = $env:COMPUTERNAME
RAMKullanim = "$([math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory)/$os.TotalVisibleMemorySize*100,1))%"
DiskUyarilari = if ($diskAlerts) { $diskAlerts -join "; " } else { "Yok" }
UptimeGun = ((Get-Date) - $os.LastBootUpTime).Days
Durum = "CEVAP VERDI"
}
} -ErrorAction Stop
$reportData += $data
}
catch {
$reportData += [PSCustomObject]@{
Sunucu = $server
RAMKullanim = "N/A"
DiskUyarilari = "N/A"
UptimeGun = "N/A"
Durum = "ERISIM HATASI"
}
}
}
# E-posta gövdesi oluştur
$body = "Haftalık Donanım Özet Raporu`n`nTarih: $reportDate`n`n"
foreach ($item in $reportData) {
$body += "[$($item.Durum)] $($item.Sunucu)`n"
$body += " RAM Kullanim: $($item.RAMKullanim)`n"
$body += " Disk Uyarilari: $($item.DiskUyarilari)`n"
$body += " Uptime: $($item.UptimeGun) gün`n`n"
}
# E-posta gönder
Send-MailMessage `
-From $From `
-To $To `
-Subject $subject `
-Body $body `
-SmtpServer $SmtpServer `
-Port $SmtpPort `
-Encoding UTF8
Write-Host "Rapor e-postası gönderildi." -ForegroundColor Green
}
# Kullanım
$sunucular = @("SRV-DC01", "SRV-FILE01", "SRV-SQL01")
Send-HardwareReport -Servers $sunucular
Pratik İpuçları ve Yaygın Hatalar
Yıllar içinde bu tür scriptler yazarken öğrendiğim bazı önemli noktaları paylaşayım.
WMI vs CIM farkı: Mümkün olduğunda Get-WmiObject yerine Get-CimInstance kullanın. WMI DCOM üzerinden çalışır ve sık sık firewall sorunlarına yol açar. CIM ise WSMan (WinRM) kullanır, daha modern ve güvenilirdir. Ancak çok eski sistemlerde (Server 2003 gibi) CIM çalışmayabilir, o durumda WMI’ya dönmek gerekir.
Byte dönüşümleri: WMI genellikle değerleri byte cinsinden döndürür. GB’a çevirmek için / 1GB, MB için / 1MB kullanın. PowerShell bu dönüşümleri otomatik yapar, manuel olarak 1073741824‘e bölmenize gerek yok.
Uzak bağlantı gereksinimleri: Invoke-Command çalıştırmadan önce hedef sunucularda WinRM aktif olmalı. Bunun için:
# Hedef sunucularda WinRM'yi etkinleştir (o sunucuda çalıştırın)
Enable-PSRemoting -Force
# Bağlantıyı test et
Test-WSMan -ComputerName "SRV-DC01"
Hata yönetimi: Toplu operasyonlarda her zaman try-catch kullanın. Bir sunucudan veri alınamazsa script durup kalan sunucuları atlamamalı.
Yetki gereksinimleri: Uzak sunuculardan WMI/CIM verisi almak için genellikle lokal admin yetkisi gerekmez, ancak WinRM bağlantısı için yeterli izinlere sahip bir hesap gereklidir. Domain ortamında bu genellikle domain admin hesabıdır ama minimum privilege principle açısından özel bir servis hesabı oluşturmak daha doğrudur.
Performans ipucu: Çok sayıda CIM sorgusunu art arda çalıştırmak yerine mümkünse CimSession kullanın. Böylece her komut için yeni bağlantı kurulmaz, mevcut oturum üzerinden sorgular yapılır.
# CimSession ile daha verimli sorgulama
$session = New-CimSession -ComputerName "SRV-FILE01"
$cpu = Get-CimInstance -CimSession $session -ClassName Win32_Processor
$ram = Get-CimInstance -CimSession $session -ClassName Win32_PhysicalMemory
$disk = Get-CimInstance -CimSession $session -ClassName Win32_LogicalDisk
Remove-CimSession -CimSession $session
Sonuç
PowerShell ile donanım ve sistem bilgisi toplamak, tek seferlik bir ihtiyacı karşılamaktan çok ötesinde bir beceri. Düzenli raporlama, kapasity planning, problem tespit etme ve audit gereksinimleri için sürekli başvuracağınız bir araçtır.
Burada anlattıklarımı kendi ortamınıza uyarlayarak başlayabilirsiniz. İlk adım olarak Get-CimInstance ile temel sorgular yapın, sonra bunları bir fonksiyona dönüştürün, ardından CSV veya HTML çıktı ekleyin. Zamanla kendi ortamınıza özel, kapsamlı bir monitoring ve raporlama altyapısı oluşturmuş olursunuz.
Scriptleri bir kaynak kontrolü sisteminde (Git gibi) tutmayı unutmayın. Üç ay önce yazdığınız script bugün hayatınızı kurtarabilir ama hangi klasörde olduğunu hatırlamıyorsanız hiçbir işe yaramaz.
