Sunucuda bir şeyler ters gittiğinde, ilk içgüdün genellikle “hangi process bunu yapıyor?” sorusunu sormak olur. Windows ortamında bu soruyu en hızlı ve en verimli şekilde yanıtlamanın yolu PowerShell’den geçiyor. Task Manager güzel bir araç, ama otomasyona gelince yetersiz kalıyor. Script yazamıyorsun, çıktıyı başka araçlarla entegre edemiyorsun, belirli koşullarda aksiyon alamıyorsun. İşte tam bu noktada PowerShell devreye giriyor ve sysadmin hayatını ciddi anlamda kolaylaştırıyor.
Temel Process Cmdlet’leri
PowerShell’de süreç yönetiminin kalbi birkaç temel cmdlet’e dayanıyor. Bunları iyi bilmeden ileri gitmek mümkün değil.
Get-Process en çok kullanacağın cmdlet. Sistemdeki çalışan tüm processleri listeler ve her biri hakkında ayrıntılı bilgi sunar.
# Tüm processleri listele
Get-Process
# Belirli bir process'i bul
Get-Process -Name "chrome"
# Birden fazla process adı ile sorgula
Get-Process -Name "chrome", "firefox", "notepad"
# Process ID ile sorgula
Get-Process -Id 1234
# Uzak bilgisayardaki processleri listele
Get-Process -ComputerName "SUNUCU01"
Bu komutun çıktısında dikkat etmen gereken bazı önemli sütunlar var:
- Handles: Process’in açık tuttuğu handle sayısı, bu sayı sürekli artıyorsa handle leak var demektir
- NPM(K): Non-paged memory kullanımı, kilobyte cinsinden
- PM(K): Paged memory kullanımı
- WS(K): Working set, yani fiziksel RAM’den ne kadar kullandığı
- CPU(s): Toplam CPU süresi, saniye cinsinden
- Id: Process ID
- ProcessName: Process adı
Process Detaylarına Derinlemesine Bakmak
Bazen yüzeysel bilgi yetmiyor. Bir process’in tam olarak ne yaptığını, hangi dosyaları kullandığını, kim tarafından başlatıldığını görmek gerekiyor.
# Belirli bir process'in tüm özelliklerini gör
Get-Process -Name "notepad" | Select-Object *
# Önemli özellikleri seç ve formatla
Get-Process | Select-Object Name, Id, CPU, WorkingSet, StartTime |
Sort-Object CPU -Descending |
Select-Object -First 10
# Process'in çalıştığı executable path'i bul
Get-Process -Name "chrome" | Select-Object Name, Id, Path
# Belirli bir process'in thread ve module bilgilerini gör
$proc = Get-Process -Name "notepad"
$proc.Threads
$proc.Modules
Gerçek dünya senaryosu olarak şunu düşün: Bir uygulama sunucusunda bellek kullanımı giderek artıyor ve ekip bunun sebebini bulamıyor. Şu komut dizisi durumu hızlıca netleştirir:
# En fazla bellek kullanan 15 process'i bul
Get-Process |
Sort-Object WorkingSet64 -Descending |
Select-Object -First 15 |
Format-Table Name, Id,
@{Name="RAM(MB)"; Expression={[math]::Round($_.WorkingSet64/1MB, 2)}},
@{Name="CPU(s)"; Expression={[math]::Round($_.CPU, 2)}},
StartTime -AutoSize
Process Başlatma ve Durdurma
Start-Process ile Process Başlatma
Task Scheduler’a gerek kalmadan, scriptlerin içinden uygulama başlatmak çok yaygın bir ihtiyaç.
# Basit uygulama başlatma
Start-Process -FilePath "notepad.exe"
# Argümanlarla başlatma
Start-Process -FilePath "cmd.exe" -ArgumentList "/c dir C: > C:cikti.txt"
# Yükseltilmiş yetkiyle (Run as Administrator) başlatma
Start-Process -FilePath "powershell.exe" -Verb RunAs
# Arka planda çalıştır ve bitene kadar bekle
Start-Process -FilePath "setup.exe" -ArgumentList "/silent" -Wait -NoNewWindow
# Belirli bir dizinde başlat
Start-Process -FilePath "python.exe" -ArgumentList "script.py" -WorkingDirectory "C:scripts"
# Çıktıyı dosyaya yönlendir
Start-Process -FilePath "cmd.exe" `
-ArgumentList "/c ipconfig /all" `
-RedirectStandardOutput "C:logsnetwork_info.txt" `
-NoNewWindow `
-Wait
Stop-Process ile Process Sonlandırma
Bu komut güçlü, bu yüzden dikkatli kullanmak lazım. Production ortamında yanlış bir process’i öldürmek ciddi sonuçlar doğurabilir.
# İsme göre process sonlandır
Stop-Process -Name "notepad"
# ID'ye göre sonlandır
Stop-Process -Id 1234
# Hata vermeden sonlandır (process yoksa bile şikayet etme)
Stop-Process -Name "notepad" -ErrorAction SilentlyContinue
# Onay istemeden zorla sonlandır
Stop-Process -Name "chrome" -Force
# Birden fazla process'i sonlandır
Get-Process -Name "chrome" | Stop-Process -Force
# Belirli bir kullanıcının processlerini sonlandır (dikkatli kullan!)
Get-Process | Where-Object {
$_.SI -eq (Get-Process -Name "explorer" | Select-Object -First 1).SI
} | Stop-Process -WhatIf
-WhatIf parametresi burada hayat kurtarıcı. Gerçekten çalıştırmadan önce ne yapacağını gösterir. Production ortamında yeni bir script denerken mutlaka kullan.
Process İzleme ve Monitoring
Anlık bilgi almak yeterli değil çoğu zaman. Sürekli izleme, trend analizi ve anomali tespiti için daha gelişmiş yaklaşımlara ihtiyaç var.
Gerçek Zamanlı Process İzleme
# Belirli aralıklarla process durumunu kontrol et
while ($true) {
Clear-Host
Write-Host "=== Process Izleme - $(Get-Date) ===" -ForegroundColor Cyan
Get-Process |
Sort-Object CPU -Descending |
Select-Object -First 20 |
Format-Table Name, Id,
@{Name="CPU(s)"; Expression={[math]::Round($_.CPU, 2)}},
@{Name="RAM(MB)"; Expression={[math]::Round($_.WorkingSet64/1MB, 2)}},
@{Name="Handles"; Expression={$_.HandleCount}} -AutoSize
Start-Sleep -Seconds 5
}
WMI ile Gelişmiş Process Bilgisi
Get-Process bazı bilgileri vermez, örneğin hangi kullanıcı hesabı altında çalıştığı. Bunun için WMI veya CIM kullanmak gerekiyor.
# Process sahibini (owner) bul
Get-CimInstance Win32_Process |
Select-Object ProcessId, Name,
@{Name="Owner"; Expression={
($_ | Invoke-CimMethod -MethodName GetOwner).User
}} |
Where-Object {$_.Owner -ne $null} |
Sort-Object Name
# Belirli bir process'in komut satırını gör (ne ile başlatıldığını)
Get-CimInstance Win32_Process -Filter "Name='chrome.exe'" |
Select-Object ProcessId, Name, CommandLine, CreationDate
# Parent process bilgisini al
Get-CimInstance Win32_Process |
Select-Object ProcessId, Name, ParentProcessId,
@{Name="ParentName"; Expression={
(Get-CimInstance Win32_Process -Filter "ProcessId=$($_.ParentProcessId)").Name
}} |
Where-Object {$_.Name -eq "powershell.exe"}
Bu komut özellikle güvenlik analizlerinde çok işe yarıyor. Hangi process’in başka hangi process’i spawn ettiğini görmek, zararlı yazılım analizi veya uygulama davranışını anlamak için kritik.
Pratik Monitoring Scriptleri
Bellek Sızıntısı Tespiti
Bir servisi günlerce izleyip bellek kullanımını log’lamak istiyorsun. İşte tam olarak bunu yapan bir script:
# Bellek kullanimini logla - memory_monitor.ps1
param(
[string]$ProcessName = "w3wp",
[int]$IntervalSeconds = 60,
[int]$ThresholdMB = 500,
[string]$LogPath = "C:logsmemory_monitor.csv"
)
# Log dosyasi yoksa baslik satiri olustur
if (-not (Test-Path $LogPath)) {
"Timestamp,ProcessName,PID,RAM_MB,CPU_seconds,Handles" |
Out-File -FilePath $LogPath -Encoding UTF8
}
Write-Host "Izleme basliyor: $ProcessName - Her $IntervalSeconds saniyede bir kontrol" -ForegroundColor Green
while ($true) {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$processes = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
if ($null -eq $processes) {
Write-Host "[$timestamp] UYARI: $ProcessName bulunamadi!" -ForegroundColor Yellow
}
else {
foreach ($proc in $processes) {
$ramMB = [math]::Round($proc.WorkingSet64 / 1MB, 2)
$cpu = [math]::Round($proc.CPU, 2)
$handles = $proc.HandleCount
# CSV'ye yaz
"$timestamp,$($proc.Name),$($proc.Id),$ramMB,$cpu,$handles" |
Add-Content -Path $LogPath -Encoding UTF8
# Esik degerini astiysa uyar
if ($ramMB -gt $ThresholdMB) {
Write-Host "[$timestamp] KRITIK: $($proc.Name) (PID:$($proc.Id)) RAM kullanimi: ${ramMB}MB - Esik: ${ThresholdMB}MB" `
-ForegroundColor Red
# Opsiyonel: Email veya event log bildirimi
Write-EventLog -LogName Application `
-Source "PowerShell Monitor" `
-EventId 9001 `
-EntryType Warning `
-Message "Process $($proc.Name) bellek kullanimi esigi asti: ${ramMB}MB" `
-ErrorAction SilentlyContinue
}
else {
Write-Host "[$timestamp] $($proc.Name) (PID:$($proc.Id)) RAM: ${ramMB}MB CPU: ${cpu}s" `
-ForegroundColor Green
}
}
}
Start-Sleep -Seconds $IntervalSeconds
}
Bu scripti şöyle çalıştırırsın:
.memory_monitor.ps1 -ProcessName "w3wp" -IntervalSeconds 30 -ThresholdMB 1000 -LogPath "C:logsiis_memory.csv"
Donmüş ya da Yanıt Vermeyen Process Tespiti
IIS uygulama havuzları, özel servisler veya herhangi bir GUI uygulaması zaman zaman yanıt vermez ama tamamen çökmez. Bunu otomatik tespit etmek:
# Yanit vermeyen processleri bul ve raporla
function Get-HangingProcesses {
param(
[string[]]$ProcessNames = @(),
[switch]$AutoKill,
[string]$LogPath = "C:logshanging_processes.log"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$hangingProcs = @()
if ($ProcessNames.Count -gt 0) {
$processes = Get-Process -Name $ProcessNames -ErrorAction SilentlyContinue
}
else {
$processes = Get-Process | Where-Object {$_.MainWindowHandle -ne 0}
}
foreach ($proc in $processes) {
if (-not $proc.Responding) {
$hangingProcs += $proc
$message = "[$timestamp] YANIT VERMIYOR: $($proc.Name) PID:$($proc.Id) RAM:$([math]::Round($proc.WorkingSet64/1MB,2))MB"
Write-Host $message -ForegroundColor Red
Add-Content -Path $LogPath -Value $message
if ($AutoKill) {
Write-Host " -> Process sonlandiriliyor..." -ForegroundColor Yellow
Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue
Add-Content -Path $LogPath -Value " -> PID $($proc.Id) sonlandirildi"
}
}
}
if ($hangingProcs.Count -eq 0) {
Write-Host "[$timestamp] Tum processler normal calisiyor." -ForegroundColor Green
}
return $hangingProcs
}
# Kullanim ornegi
Get-HangingProcesses -ProcessNames @("notepad", "chrome", "outlook") -LogPath "C:logsapp_health.log"
Process Priority ve CPU Affinity Yönetimi
Yoğun bir sunucuda bazı processlerin diğerlerinden daha fazla CPU almasını isteyebilirsin. Ya da tam tersi, arka plan işlemlerinin kritik servisleri etkilememesini isteyebilirsin.
# Process önceliğini görüntüle
Get-Process | Select-Object Name, Id, PriorityClass | Sort-Object PriorityClass
# Process önceliğini değiştir
$proc = Get-Process -Name "backup_tool"
$proc.PriorityClass = [System.Diagnostics.ProcessPriorityClass]::BelowNormal
# Öncelik seviyeleri:
# Idle, BelowNormal, Normal, AboveNormal, High, RealTime
# CPU Affinity ayarla (hangi CPU core'larini kullanacagini belirle)
# Bu ornek sadece ilk 2 core'u kullanmasini saglar (core 0 ve 1 = binary 11 = decimal 3)
$proc = Get-Process -Name "heavy_app"
$proc.ProcessorAffinity = 3 # Binary: 0011 = Core 0 ve Core 1
# 8 core'lu sistemde sadece son 4 core'u kullanmak icin
# Binary: 11110000 = Decimal 240
$proc.ProcessorAffinity = 240
Scheduled Task ile Process Monitoring Otomasyonu
Tüm bu güzel scriptler sürekli elle çalıştırılırsa pek işe yaramaz. Task Scheduler ile otomasyona bağlamak gerekiyor.
# Scheduled Task olustur - her 5 dakikada bir process kontrolu
$action = New-ScheduledTaskAction `
-Execute "PowerShell.exe" `
-Argument "-NonInteractive -WindowStyle Hidden -File C:scriptsprocess_monitor.ps1"
$trigger = New-ScheduledTaskTrigger `
-RepetitionInterval (New-TimeSpan -Minutes 5) `
-Once `
-At (Get-Date)
$settings = New-ScheduledTaskSettingsSet `
-ExecutionTimeLimit (New-TimeSpan -Minutes 4) `
-RestartCount 3 `
-RestartInterval (New-TimeSpan -Minutes 1)
$principal = New-ScheduledTaskPrincipal `
-UserId "SYSTEM" `
-LogonType ServiceAccount `
-RunLevel Highest
Register-ScheduledTask `
-TaskName "ProcessMonitor" `
-TaskPath "SysAdminMonitoring" `
-Action $action `
-Trigger $trigger `
-Settings $settings `
-Principal $principal `
-Description "Her 5 dakikada bir kritik processleri izler" `
-Force
Write-Host "Scheduled Task basariyla olusturuldu." -ForegroundColor Green
Event Log’a Process Olaylarını Kaydetme
Process başlama ve bitme olaylarını Windows Event Log’a kaydetmek, sorun analizi için çok değerli bir izlek oluşturur.
# Belirli bir process basladiginda event log'a yaz
Register-WmiEvent -Query "SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName='suspicious.exe'" `
-Action {
$proc = $Event.SourceEventArgs.NewEvent
$message = "Supheli process basladi: $($proc.ProcessName) PID:$($proc.ProcessID)"
Write-EventLog -LogName Security `
-Source "Application" `
-EventId 4688 `
-EntryType Warning `
-Message $message
# Aninda bildirim icin email de gonderebilirsin
Write-Host "UYARI: $message" -ForegroundColor Red
}
# Bu noktada event bekleniyor, Ctrl+C ile dur
Write-Host "Process izleme aktif. Durdurmak icin Ctrl+C..." -ForegroundColor Yellow
while ($true) { Start-Sleep -Seconds 1 }
Performans Sayaçları ile Derinlemesine Analiz
Get-Counter cmdlet’i, Performance Monitor’ın sunduğu tüm metriklere PowerShell üzerinden erişmeni sağlar.
# Belirli bir process icin detayli performans metrikleri
$processName = "w3wp"
# Mevcut sayaclari listele
Get-Counter -ListSet "Process" | Select-Object -ExpandProperty Counter
# CPU ve bellek kullanimi
$counters = @(
"Process($processName*)% Processor Time",
"Process($processName*)Working Set",
"Process($processName*)Handle Count",
"Process($processName*)Thread Count"
)
# 10 saniye boyunca 2 saniyede bir ölç
Get-Counter -Counter $counters -SampleInterval 2 -MaxSamples 5 |
ForEach-Object {
$_.CounterSamples |
Select-Object @{Name="Zaman"; Expression={$_.Timestamp.ToString("HH:mm:ss")}},
InstanceName,
@{Name="Deger"; Expression={[math]::Round($_.CookedValue, 2)}},
Path
}
Sonuç
PowerShell ile process yönetimi, Task Manager’ın çok ötesine geçen bir kabiliyetler seti sunuyor. Burada ele aldığımız konuları özetlemek gerekirse:
- Get-Process ve Get-CimInstance kombinasyonu, processlerin sahip bilgisi ve komut satırı argümanları dahil tam resmini ortaya koyuyor
- Start-Process ve Stop-Process ile script içinden güvenli ve kontrollü process yönetimi yapabiliyorsun
- Döngüsel monitoring scriptleri ile bellek sızıntısı ve donmuş process tespitini otomatize edebiliyorsun
- ProcessorAffinity ve PriorityClass ile CPU kaynak yönetimini ince ayar yapabiliyorsun
- Register-WmiEvent ile gerçek zamanlı process olaylarına tepki verebiliyorsun
- Get-Counter ile derinlemesine performans analizi yapabiliyorsun
Gerçek fark yaratmak için bu scriptleri organizasyonunun ihtiyaçlarına göre uyarlamak, Scheduled Task ile otomasyona bağlamak ve çıktıları merkezi bir log sistemine göndermek gerekiyor. Bir sysadmin olarak asıl hedef, problemleri oluşmadan önce tespit edecek sistemleri kurmak. Bu scriptler tam olarak bunun için bir başlangıç noktası.
Bir sonraki adım olarak bu monitoring verilerini Grafana veya Splunk gibi araçlara beslemek düşünülebilir, ancak o konu başlı başına ayrı bir yazıyı hak ediyor.