Veri işleme konusuna gelince, sysadmin’lerin en çok zaman harcadığı alanlardan biri hiç şüphesiz JSON ve XML formatlarıdır. API entegrasyonları, konfigürasyon dosyaları, log çıktıları… Her yerde bu iki format karşımıza çıkıyor. PowerShell bu konuda gerçekten güçlü araçlar sunuyor ve bir kez öğrendiğinizde hayatınız ciddi ölçüde kolaylaşıyor. Gelin bu iki formatı PowerShell ile nasıl verimli şekilde işleyebileceğimize detaylıca bakalım.
JSON ile Çalışmak
JSON (JavaScript Object Notation), özellikle REST API’larla çalışırken ve modern konfigürasyon dosyalarında sıklıkla karşılaşılan bir format. PowerShell 3.0’dan itibaren gelen ConvertTo-Json ve ConvertFrom-Json cmdlet’leri bu işi oldukça kolaylaştırıyor.
ConvertFrom-Json ile JSON Okuma
Elimizde bir JSON verisi olduğunda bunu PowerShell objesine çevirmek için ConvertFrom-Json kullanıyoruz. Basit bir örnekle başlayalım:
# Basit JSON string'ini PowerShell objesine çevirme
$jsonString = '{"hostname": "WEB-SRV-01", "ip": "192.168.1.10", "port": 8080, "active": true}'
$serverInfo = $jsonString | ConvertFrom-Json
# Özelliklere erişim
Write-Host "Sunucu: $($serverInfo.hostname)"
Write-Host "IP Adresi: $($serverInfo.ip)"
Write-Host "Port: $($serverInfo.port)"
Write-Host "Aktif mi: $($serverInfo.active)"
Dikkat ettiyseniz JSON’daki true değeri PowerShell’de otomatik olarak $true boolean değerine dönüşüyor. Bu tür tip dönüşümlerini PowerShell bizim için otomatik yapıyor, bu büyük bir kolaylık.
Gerçek Dünya Senaryosu: Sunucu Envanter Dosyası Okuma
Diyelim ki elinizde sunucu envanterinizi tutan bir JSON dosyası var ve bu dosyadan belirli kriterlere göre sunucuları filtrelemek istiyorsunuz:
# sunucu_envanter.json dosyasını oku ve işle
$envanter = Get-Content -Path "C:Scriptssunucu_envanter.json" -Raw | ConvertFrom-Json
# Sadece aktif Windows sunucularını getir
$aktifSunucular = $envanter.sunucular | Where-Object {
$_.aktif -eq $true -and $_.os -like "*Windows*"
}
# Aktif sunucuları listele
foreach ($sunucu in $aktifSunucular) {
Write-Host "Sunucu: $($sunucu.hostname) | IP: $($sunucu.ip) | OS: $($sunucu.os)"
# Disk kullanımı yüksek olanları işaretle
if ($sunucu.diskKullanim -gt 85) {
Write-Warning "UYARI: $($sunucu.hostname) disk kullanimi kritik seviyede! (%$($sunucu.diskKullanim))"
}
}
ConvertTo-Json ile JSON Oluşturma
Veriyi JSON formatına çevirmek de oldukça basit. ConvertTo-Json cmdlet’inin -Depth parametresi özellikle iç içe objelerde kritik öneme sahip:
# Sistem bilgilerini toplayıp JSON'a çevirme
$sistemBilgisi = [PSCustomObject]@{
Hostname = $env:COMPUTERNAME
Tarih = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
OS = (Get-WmiObject Win32_OperatingSystem).Caption
RAM_GB = [math]::Round((Get-WmiObject Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
CPU_Cekirdek = (Get-WmiObject Win32_Processor).NumberOfCores
DiskBilgisi = Get-WmiObject Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3} | ForEach-Object {
[PSCustomObject]@{
Surucu = $_.DeviceID
Toplam_GB = [math]::Round($_.Size / 1GB, 2)
Bos_GB = [math]::Round($_.FreeSpace / 1GB, 2)
Doluluk = [math]::Round((($_.Size - $_.FreeSpace) / $_.Size) * 100, 1)
}
}
}
# JSON'a çevir ve dosyaya kaydet
# -Depth parametresi iç içe objelerin kaç seviye derine gidileceğini belirler
$sistemBilgisi | ConvertTo-Json -Depth 4 | Out-File -FilePath "C:Raporlarsistem_bilgisi.json" -Encoding UTF8
Write-Host "Sistem bilgileri JSON formatinda kaydedildi."
-Depth parametresine dikkat edin. Varsayılan değeri 2’dir ve iç içe objeleriniz varsa bu değeri artırmazsanız veriler kesilebilir. Ben genellikle 4 ya da 5 kullanmayı tercih ediyorum.
API’dan JSON Veri Çekme
Gerçek hayatta en sık kullanılan senaryo REST API’lardan veri çekmek. Örneğin bir monitoring API’ından sunucu durumlarını çekelim:
# REST API'dan JSON veri çekme ve işleme
function Get-SunucuDurumu {
param(
[string]$ApiUrl = "https://monitoring.sirket.local/api/servers",
[string]$ApiKey = "your-api-key-here"
)
try {
$headers = @{
"Authorization" = "Bearer $ApiKey"
"Content-Type" = "application/json"
}
$response = Invoke-RestMethod -Uri $ApiUrl -Headers $headers -Method GET
# Kritik durumda olan sunucuları filtrele
$kritikSunucular = $response.data | Where-Object { $_.status -eq "critical" }
if ($kritikSunucular.Count -gt 0) {
Write-Warning "Kritik durumda $($kritikSunucular.Count) sunucu tespit edildi!"
foreach ($sunucu in $kritikSunucular) {
Write-Host "KRITIK: $($sunucu.name) - Sorun: $($sunucu.issue)" -ForegroundColor Red
# Olay kaydı oluştur
$olay = [PSCustomObject]@{
Zaman = Get-Date -Format "yyyy-MM-ddTHH:mm:ss"
Sunucu = $sunucu.name
Durum = $sunucu.status
Detay = $sunucu.issue
}
$olay | ConvertTo-Json | Add-Content -Path "C:Logskritik_olaylar.json"
}
}
return $response
}
catch {
Write-Error "API baglantisi kurulamadi: $($_.Exception.Message)"
}
}
XML ile Çalışmak
XML, özellikle eski enterprise uygulamalar, Windows konfigürasyon dosyaları ve SCCM/WSUS gibi Microsoft araçlarında hala çok yaygın. PowerShell’in XML desteği de oldukça kapsamlı.
XML Dosyası Okuma
PowerShell’de XML ile çalışmanın en temiz yolu [xml] type accelerator kullanmak:
# XML dosyasını okuma ve işleme
[xml]$config = Get-Content -Path "C:Configsuygulama_ayarlari.xml" -Encoding UTF8
# XML düğümlerine nokta notasyonuyla erişim
$dbServer = $config.Configuration.Database.Server
$dbPort = $config.Configuration.Database.Port
$dbName = $config.Configuration.Database.Name
$logLevel = $config.Configuration.Logging.Level
Write-Host "Veritabani Sunucusu: $dbServer"
Write-Host "Port: $dbPort"
Write-Host "Veritabani Adi: $dbName"
Write-Host "Log Seviyesi: $logLevel"
# Birden fazla eleman içeren düğümleri döngüyle işleme
foreach ($kullanici in $config.Configuration.Users.User) {
Write-Host "Kullanici: $($kullanici.username) | Rol: $($kullanici.role) | Aktif: $($kullanici.active)"
}
XML Oluşturma ve Düzenleme
XML oluşturmak biraz daha fazla kod gerektiriyor ama System.Xml.XmlDocument sınıfını kullanarak oldukça temiz XML dosyaları üretebilirsiniz:
# Sıfırdan XML dosyası oluşturma
function Yeni-KonfigurasyonXML {
param(
[string]$CiktiDosyasi = "C:Configsyeni_config.xml"
)
# XML dökümanı oluştur
$xmlDoc = New-Object System.Xml.XmlDocument
# XML deklarasyonu ekle
$xmlDecl = $xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", $null)
$xmlDoc.AppendChild($xmlDecl) | Out-Null
# Kök element
$rootNode = $xmlDoc.CreateElement("Configuration")
$xmlDoc.AppendChild($rootNode) | Out-Null
# Sunucu bilgileri bölümü
$serverNode = $xmlDoc.CreateElement("ServerSettings")
$serverNode.SetAttribute("version", "2.0")
$serverNode.SetAttribute("lastUpdated", (Get-Date -Format "yyyy-MM-dd"))
# Alt elementler ekle
$hostnameNode = $xmlDoc.CreateElement("Hostname")
$hostnameNode.InnerText = $env:COMPUTERNAME
$serverNode.AppendChild($hostnameNode) | Out-Null
$maxConnNode = $xmlDoc.CreateElement("MaxConnections")
$maxConnNode.InnerText = "500"
$serverNode.AppendChild($maxConnNode) | Out-Null
$timeoutNode = $xmlDoc.CreateElement("TimeoutSeconds")
$timeoutNode.InnerText = "30"
$serverNode.AppendChild($timeoutNode) | Out-Null
$rootNode.AppendChild($serverNode) | Out-Null
# Dosyaya kaydet
$xmlDoc.Save($CiktiDosyasi)
Write-Host "XML konfigurasyonu olusturuldu: $CiktiDosyasi" -ForegroundColor Green
}
Yeni-KonfigurasyonXML
Gerçek Dünya Senaryosu: Windows Event Log XML Analizi
Windows Event Log’larının XML formatındaki verisini analiz etmek, özellikle güvenlik denetimleri için çok işe yarıyor:
# Son 24 saatteki başarısız oturum açma girişimlerini XML üzerinden analiz etme
function Analiz-BasarisizGirisler {
param(
[int]$SaatGeriye = 24,
[int]$EsikDeger = 5
)
$baslangicZamani = (Get-Date).AddHours(-$SaatGeriye)
# Security event log'dan Event ID 4625 (başarısız giriş) olaylarını çek
$olaylar = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4625
StartTime = $baslangicZamani
} -ErrorAction SilentlyContinue
if (-not $olaylar) {
Write-Host "Belirtilen zaman araliginda basarisiz giris denemesi bulunamadi."
return
}
# Her olayın XML verisini parse et
$girisDenemeler = foreach ($olay in $olaylar) {
[xml]$xmlVeri = $olay.ToXml()
# EventData içinden ilgili alanları çek
$eventData = $xmlVeri.Event.EventData.Data
[PSCustomObject]@{
Zaman = $olay.TimeCreated
KullaniciAdi = ($eventData | Where-Object { $_.Name -eq "TargetUserName" }).'#text'
KaynakIP = ($eventData | Where-Object { $_.Name -eq "IpAddress" }).'#text'
Workstation = ($eventData | Where-Object { $_.Name -eq "WorkstationName" }).'#text'
HataKodu = ($eventData | Where-Object { $_.Name -eq "SubStatus" }).'#text'
}
}
# IP bazında gruplama ve eşik değeri aşanları bul
$supheli = $girisDenemeler | Group-Object -Property KaynakIP |
Where-Object { $_.Count -ge $EsikDeger } |
Sort-Object Count -Descending
if ($supheli.Count -gt 0) {
Write-Warning "GUVENLIK UYARISI: $($supheli.Count) suphelie IP tespit edildi!"
foreach ($ip in $supheli) {
Write-Host "IP: $($ip.Name) | Deneme Sayisi: $($ip.Count)" -ForegroundColor Yellow
}
}
# Sonuçları JSON formatında kaydet
$girisDenemeler | ConvertTo-Json -Depth 3 |
Out-File "C:Guvenlikbasarisiz_girisler_$(Get-Date -Format 'yyyyMMdd').json" -Encoding UTF8
return $girisDenemeler
}
Analiz-BasarisizGirisler -SaatGeriye 48 -EsikDeger 10
JSON ve XML Arasında Dönüşüm
Zaman zaman bir formattan diğerine dönüştürme ihtiyacı da çıkıyor. Bu oldukça kolay:
# XML'den JSON'a dönüşüm
function Cevir-XMLdenJSON {
param(
[string]$XmlDosyasi,
[string]$JsonCikti
)
[xml]$xmlVeri = Get-Content -Path $XmlDosyasi -Encoding UTF8
# XML'i önce hashtable'a, sonra JSON'a çevir
$jsonVeri = $xmlVeri | ConvertTo-Json -Depth 10
$jsonVeri | Out-File -FilePath $JsonCikti -Encoding UTF8
Write-Host "Donusum tamamlandi: $XmlDosyasi --> $JsonCikti" -ForegroundColor Green
Write-Host "JSON boyutu: $([math]::Round((Get-Item $JsonCikti).Length / 1KB, 2)) KB"
}
# JSON'dan XML'e dönüşüm
function Cevir-JSONdenXML {
param(
[string]$JsonDosyasi,
[string]$XmlCikti
)
$jsonVeri = Get-Content -Path $JsonDosyasi -Raw | ConvertFrom-Json
# PowerShell objesini XML'e çevirme
$xmlDoc = New-Object System.Xml.XmlDocument
$rootNode = $xmlDoc.CreateElement("Root")
$xmlDoc.AppendChild($rootNode) | Out-Null
function Ekle-XMLDugumu {
param($ParentNode, $Veri, $AnahtarAdi)
if ($Veri -is [PSCustomObject] -or $Veri -is [hashtable]) {
$dugum = $xmlDoc.CreateElement($AnahtarAdi)
$Veri.PSObject.Properties | ForEach-Object {
Ekle-XMLDugumu -ParentNode $dugum -Veri $_.Value -AnahtarAdi $_.Name
}
$ParentNode.AppendChild($dugum) | Out-Null
} else {
$dugum = $xmlDoc.CreateElement($AnahtarAdi)
$dugum.InnerText = "$Veri"
$ParentNode.AppendChild($dugum) | Out-Null
}
}
$jsonVeri.PSObject.Properties | ForEach-Object {
Ekle-XMLDugumu -ParentNode $rootNode -Veri $_.Value -AnahtarAdi $_.Name
}
$xmlDoc.Save($XmlCikti)
Write-Host "Donusum tamamlandi: $JsonDosyasi --> $XmlCikti" -ForegroundColor Green
}
Performans ve Best Practice Önerileri
Büyük dosyalarla çalışırken dikkat etmeniz gereken bazı noktalar var:
- Büyük JSON dosyalarında
Get-Content -Rawkullanın, satır satır okumak çok daha yavaş çalışır -Depthparametresini ihtiyacınıza göre ayarlayın, gereğinden yüksek değer performansı olumsuz etkiler- XML için
Select-Xmlcmdlet’i XPath sorguları için çok güçlü bir alternatiftir, büyük XML dosyalarında düğüm araması yaparken tercih edin - Encoding sorunları için her zaman
-Encoding UTF8parametresini açıkça belirtin, özellikle Türkçe karakter içeren dosyalarda bu kritik - Hata yönetimi için
try-catchbloklarını ihmal etmeyin, özellikle API çağrılarında ve dosya işlemlerinde
# Select-Xml ile XPath sorgusu - büyük XML dosyalarında çok daha verimli
$xpathSorgu = "//User[@active='true']"
$aktifKullanicilar = Select-Xml -Path "C:Configskullanicilar.xml" -XPath $xpathSorgu
foreach ($sonuc in $aktifKullanicilar) {
$kullanici = $sonuc.Node
Write-Host "Kullanici: $($kullanici.username) | Email: $($kullanici.email)"
}
Sonuç
PowerShell ile JSON ve XML işleme konusunu bir kez iyice kavradığınızda, günlük sysadmin görevlerinizin büyük kısmını otomatize edebiliyorsunuz. API entegrasyonları, konfigürasyon yönetimi, log analizi, raporlama… Bunların hepsi bu bilgiler üzerine inşa ediliyor.
Özellikle şu noktalara odaklanmanızı öneririm: ConvertFrom-Json ve ConvertTo-Json ikilisini iyice sindirin çünkü modern ortamlarda JSON her yerde karşınıza çıkacak. XML tarafında ise [xml] type accelerator ile başlayın, büyük dosyalar için Select-Xml ve XPath sorgularına geçin. Dönüşüm senaryolarında -Depth parametresini asla unutmayın.
Yazdığınız scriptleri modüler tutun, her veri işleme işlemi için ayrı fonksiyonlar yazın ve encoding’e dikkat edin. Türkçe karakter sorunları genellikle UTF-8 belirtilmediğinde ortaya çıkıyor ve bunlar en sinir bozucu bug’lar arasında yer alıyor. Bir kez düzgün alışkanlıklar edindikten sonra bu işlerin ne kadar pratik olduğunu göreceksiniz.