PowerShell ile Süreç (Process) Yönetimi ve İzleme

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.

Yorum yapın