Bu makalede9 bölüm
- Teknoloji
- PowerShell 5.1/7, WinRM, PowerShell Remoting, ActiveDirectory modülü, Task Scheduler, gMSA
- Konu
- Tekrarlanan sunucu işlerinin betiklenmesi
- Seviye
- Orta
- Ön koşullar
- Temel PowerShell sözdizimi bilgisi
- Etki alanına üye Windows Server ortamı
- RSAT ActiveDirectory modülü
Her sabah sunuculara tek tek RDP ile girip disk alanına bakmak, her ay pasif hesapları elle listelemek, log klasörünü birim dolduğunda hatırlamak: bunların hepsi unutulmaya açık işlerdir ve bir gün unutulur. PowerShell bu tekrarları betiğe çevirir. Aşağıda sistem ekiplerinin en sık elle yaptığı işler için çalışan örnekler var; birden fazla sunucuda uzaktan çalıştırma, zamanlanmış görev olarak işletme, hata yönetimi ve betiklerin kurum içinde düzende tutulması da dahil.
Hangi işler otomasyona uygundur
Her işi betiklemek mantıklı değildir. İyi adayların ortak özellikleri vardır:
- Tekrarlanır: Günlük, haftalık veya her yeni kullanıcı/sunucu için aynı adımlar.
- Kurala bağlıdır: “90 gündür oturum açmamış hesaplar” gibi net bir ölçütü vardır; insan yorumu gerektirmez.
- Hata maliyeti yönetilebilir: Önce raporlayan, sonra onayla değiştiren bir yapıya oturur.
Pratikte bu, raporlamayla başlamak demektir. Rapor betiği ortamı değiştirmez; yanlış çalışırsa yanlış rapor üretir, o kadar. Değişiklik yapan betiklere (hesap devre dışı bırakma, dosya silme) raporlar birkaç hafta doğru sonuç verdikten sonra geçin. Önce oku, sonra yaz.
PowerShell Remoting ve Invoke-Command
Çoklu sunucu yönetiminin temeli WinRM üzerinden çalışan PowerShell Remoting’dir. Windows Server’da varsayılan olarak etkindir; kapalıysa Enable-PSRemoting -Force ile açılır. Etki alanı içinde kimlik doğrulama Kerberos ile yapılır; trafik HTTP (5985/TCP) üzerinde olsa bile Kerberos oturumu tarafından şifrelenir. Etki alanı dışı sunucular için HTTPS dinleyicisi (5986/TCP) ve sertifika gerekir. Bağlantı kurulamıyorsa ilk kontrol sırası şudur: hedefte WinRM hizmeti çalışıyor mu, güvenlik duvarı portu açık mı, adı DNS’te doğru IP’ye çözülüyor mu. Test-WSMan sunucuadi WinRM uç noktasına ulaşılıp ulaşılmadığını tek komutla gösterir.
Invoke-Command betik bloğunu listedeki tüm sunucularda paralel çalıştırır (varsayılan eşzamanlılık sınırı 32, -ThrottleLimit ile değişir) ve her sonuca kaynak sunucuyu gösteren PSComputerName özelliğini ekler:
$servers = Get-Content "C:\Scripts\servers.txt"
Invoke-Command -ComputerName $servers -ScriptBlock {
(Get-CimInstance Win32_OperatingSystem).LastBootUpTime
} | Select-Object PSComputerName, @{n='SonAcilis';e={$_}}
Aynı sunuculara art arda çok komut gönderecekseniz her seferinde yeni bağlantı kurmak yerine New-PSSession ile oturumları bir kez açıp Invoke-Command -Session $s ile yeniden kullanın; fark belirgindir. En sık takılınan tuzak “double hop” sorunudur: uzak oturumun içinden üçüncü bir kaynağa, örneğin bir dosya paylaşımına erişim, kimlik bilgisi varsayılan olarak devredilmediği için “Access denied” ile düşer. Komut yerelde çalışır, uzakta çalışmaz, ekip saatlerce izin arar. En sade çözüm, sonucu yerel makineye döndürüp dosyayı yerelde yazmaktır. Uzak oturumdan kaynağa erişim gerçekten gerekiyorsa kaynak tabanlı Kerberos kısıtlı yetki devri (resource-based constrained delegation) tercih edin. Kimlik bilgisini uzak sunucuya bırakan CredSSP’yi ancak riskini tarttıktan sonra kullanın.
Örnek: disk ve hizmet durumu raporu
Aşağıdaki betik sabit disklerin boş alanını ve otomatik başlaması gerektiği halde çalışmayan hizmetleri tüm sunuculardan toplar:
$servers = Get-Content "C:\Scripts\servers.txt"
$tarih = Get-Date -Format "yyyy-MM-dd"
$disk = Invoke-Command -ComputerName $servers -ScriptBlock {
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" |
Select-Object DeviceID,
@{n='BoyutGB';e={[math]::Round($_.Size/1GB,1)}},
@{n='BosGB';e={[math]::Round($_.FreeSpace/1GB,1)}},
@{n='BosOran';e={[math]::Round($_.FreeSpace/$_.Size*100,1)}}
} | Select-Object PSComputerName, DeviceID, BoyutGB, BosGB, BosOran
$disk | Where-Object BosOran -lt 15 |
Export-Csv "C:\Raporlar\disk-$tarih.csv" -NoTypeInformation -Encoding UTF8
$hizmet = Invoke-Command -ComputerName $servers -ScriptBlock {
Get-CimInstance Win32_Service -Filter "StartMode='Auto' AND State<>'Running'" |
Select-Object Name, DisplayName, State
} | Select-Object PSComputerName, Name, DisplayName, State
$hizmet | Export-Csv "C:\Raporlar\hizmet-$tarih.csv" -NoTypeInformation -Encoding UTF8
Hizmet raporunda bazı hizmetler doğası gereği durmuş görünür: “Automatic (Delayed Start)” ya da tetikleyiciyle başlayan hizmetler gibi. Bunları bir dışlama listesiyle filtrelemezseniz rapor her gün aynı gürültüyü üretir ve ikinci haftada okunmaz olur. Sürekli izleme tarafı sunucu izleme metrikleri ve eşik değerleri yazısında anlatılıyor. Betik raporu izleme sisteminin yerine geçmez; onun yakalamadığı envanter boşluklarını görmek içindir.
Örnek: AD hesap raporları
ActiveDirectory modülüyle (RSAT veya etki alanı denetleyicisi üzerinde) kullanılmayan ve riskli hesaplar raporlanır:
Import-Module ActiveDirectory
# 90 gündür oturum açmamış, etkin kullanıcılar
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -UsersOnly |
Where-Object Enabled |
Select-Object Name, SamAccountName, LastLogonDate, DistinguishedName |
Export-Csv "C:\Raporlar\pasif-kullanicilar.csv" -NoTypeInformation -Encoding UTF8
# Parolası hiç sona ermeyen etkin kullanıcılar
Get-ADUser -Filter 'Enabled -eq $true -and PasswordNeverExpires -eq $true' `
-Properties PasswordLastSet, PasswordNeverExpires |
Select-Object Name, SamAccountName, PasswordLastSet
# 90 gündür etki alanına bağlanmamış bilgisayarlar
Search-ADAccount -AccountInactive -TimeSpan 90.00:00:00 -ComputersOnly |
Where-Object Enabled |
Select-Object Name, LastLogonDate, DistinguishedName
LastLogonDate, replike edilen lastLogonTimestamp özniteliğinden türetilir. Bu öznitelik ancak önceki değer belirli bir aralıktan (varsayılan 14 gün, rastgele sapmayla) eskiyse güncellenir. Yani değer gerçek son oturumdan iki haftaya kadar geride olabilir. 90 günlük eşik için önemsizdir; “dün oturum açtı mı?” sorusuna ise yanıt vermez. Raporu devre dışı bırakma adımına bağlamadan önce hizmet ve yönetici hesaplarını dışlama listesine alın. Aksi halde bir gece yarısı bir uygulamanın hizmet hesabı kapanır ve sabah ilk telefon gelir. Hesap raporları, dizinin genel sağlığıyla birlikte Active Directory sağlık kontrolü sürecinin parçası olarak çalıştırılabilir.
Örnek: log temizliği
IIS, uygulama veya yedek ajanı logları zamanla birimi doldurur ve birim dolduğunda servis durur. Silme yapan betikte her zaman önce -WhatIf ile deneyin:
$gun = 30
Get-ChildItem -Path "D:\Logs\IIS" -Filter *.log -Recurse -File |
Where-Object LastWriteTime -lt (Get-Date).AddDays(-$gun) |
Remove-Item -WhatIf # sonucu doğruladıktan sonra -WhatIf kaldırılır
Silmeden önce saklama süresinin kurum politikası, denetim veya yasal yükümlülüklerle çelişmediğini doğrulayın. Bazı loglar silinmez, arşiv birimine taşınır. Yol değişkenini yanlış yazan bir silme betiği, ikinci denemeye fırsat bırakmaz.
Zamanlanmış görevler ile çalıştırma
Betikler ScheduledTasks modülüyle zamanlanmış görev olarak kaydedilir. Görevi kişisel yönetici hesabıyla çalıştırmak iki ayrı sorun doğurur: parola değiştiğinde görev sessizce bozulur, kişi şirketten ayrıldığında hesabı kapatan ekip farkında olmadan raporları da kapatır. Etki alanında doğru seçenek, parolasını AD’nin otomatik yönettiği grup yönetilen hizmet hesabıdır (gMSA). Hesap oluşturulup sunucuda Install-ADServiceAccount ile kurulduktan ve Test-ADServiceAccount ile doğrulandıktan sonra:
$action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument '-NoProfile -File "C:\Scripts\DiskRaporu.ps1"'
$trigger = New-ScheduledTaskTrigger -Daily -At 07:00
$principal = New-ScheduledTaskPrincipal -UserId 'CORP\gmsa-rapor$' -LogonType Password
Register-ScheduledTask -TaskName "Gunluk Disk Raporu" -Action $action `
-Trigger $trigger -Principal $principal
gMSA için -LogonType Password belirtilir ama parola girilmez; parola AD’den alınır. Hesabın sunucuda “Toplu iş olarak oturum aç” (Log on as a batch job) hakkı olmalı. Bu hak yoksa görev kaydedilir ama çalışmaz; görev geçmişinde oturum hatası görürsünüz. Hesaba yalnız betiğin ihtiyacı olan yetkiyi verin. AD raporu için okuma yetkisi yeter. Domain Admins üyeliği gereksiz ve risklidir.
Hata yönetimi ve loglama
Zamanlanmış görevde çalışan betiğin hatası ekrana yazılmaz. Kimse görmez. Bu yüzden:
- PowerShell’de çoğu hata “sonlandırmayan” (non-terminating) türdedir ve
try/catchtarafından yakalanmaz. Kritik komutlara-ErrorAction Stopekleyin veya betiğin başında$ErrorActionPreference = 'Stop'tanımlayın. - Her çalışmayı zaman damgalı bir log dosyasına yazın.
Start-Transcripthızlı başlangıçtır; yapılandırılmış log (tarih, seviye, sunucu, mesaj) sonradan aramayı kolaylaştırır. - Ulaşılamayan sunucuları ayrıca raporlayın.
Invoke-Commandile bağlanılamayan sunucular-ErrorVariableile toplanabilir; aksi halde rapor eksik ama “başarılı” görünür. Sahada en tehlikeli rapor budur. - Başarısızlıkta sıfırdan farklı çıkış kodu döndürün (
exit 1); zamanlanmış görev geçmişi ve izleme sistemi bunu görür.
$ErrorActionPreference = 'Stop'
$log = "C:\Scripts\Logs\DiskRaporu-$(Get-Date -Format yyyyMMdd).log"
function Write-Log($Seviye, $Mesaj) {
"{0:yyyy-MM-dd HH:mm:ss} [{1}] {2}" -f (Get-Date), $Seviye, $Mesaj |
Add-Content -Path $log -Encoding UTF8
}
try {
Write-Log INFO "Rapor başladı"
# ... iş mantığı ...
Write-Log INFO "Rapor tamamlandı"
}
catch {
Write-Log ERROR $_.Exception.Message
exit 1
}
E-posta ile rapor göndermek için hâlâ sık görülen Send-MailMessage cmdlet’i Microsoft tarafından kullanılmaması önerilen (obsolete) olarak işaretlenmiştir. Yeni betiklerde kurumun desteklediği bir posta yöntemini kullanın ya da raporu bir paylaşıma bırakın.
Betik yönetimi ve sürüm kontrolü
Sunucu masaüstlerine dağılmış, adı yeni_son2.ps1 olan betikler sunucu yönetimi otomasyonunun en büyük işletim riskidir. Hangisinin çalıştığını kimse bilmez. Sürdürülebilir düzen için:
- Tüm betikleri bir Git deposunda tutun; değişiklikleri gözden geçirmeyle birleştirin.
- Ortak fonksiyonları (loglama, sunucu listesi okuma) bir modülde (
.psm1ve.psd1) toplayın. - Parola, API anahtarı gibi bilgileri betiğe yazmayın; gMSA, Windows kimlik bilgisi deposu veya Microsoft.PowerShell.SecretManagement modülü kullanın.
#Requires -Modules ActiveDirectorygibi bildirimlerle bağımlılıkları açık yazın;Invoke-ScriptAnalyzer(PSScriptAnalyzer) ile statik kontrol yapın.- Yürütme ilkesini (execution policy)
RemoteSigned, kod imzalama altyapınız varsaAllSignedyapın. Microsoft’un da belirttiği gibi bu ilke bir güvenlik sınırı değil, istemeden betik çalıştırmayı önleyen bir korumadır.
Otomasyonu yama ve bakım süreçleriyle birleştirmek için sunucu yama yönetimi yazısı, GPO ile yapılan yapılandırmaları doğrulamak için Group Policy sorun giderme yazısı tamamlayıcıdır. Ekip içi PowerShell yetkinliğini geliştirmek bilişim danışmanlığı ve eğitim kapsamında planlanabilir. Resmi kaynaklar: Microsoft Learn’de about_Remote ve about_Execution_Policies.
Sık sorulan sorular
Invoke-Command için sunucularda ne yapılandırılmalı?
Etki alanına üye Windows Server sürümlerinde PowerShell Remoting varsayılan olarak etkindir. Kapalıysa Enable-PSRemoting -Force ile açılır; güvenlik duvarında WinRM için 5985/TCP, HTTPS kullanılıyorsa 5986/TCP izni gerekir.
try/catch neden bazı hataları yakalamıyor?
PowerShell’de birçok cmdlet hatası sonlandırmayan türdedir ve catch bloğuna düşmez. Komuta -ErrorAction Stop eklemek veya $ErrorActionPreference değerini Stop yapmak bu hataları yakalanabilir hale getirir.
Zamanlanmış görev hangi hesapla çalışmalı?
Etki alanında grup yönetilen hizmet hesabı (gMSA); parolasını AD otomatik değiştirir. Hesaba yalnızca betiğin ihtiyaç duyduğu en düşük yetkiyi verin.
Execution policy betikleri güvenli hale getirir mi?
Hayır. Yürütme ilkesi bir güvenlik sınırı değildir; yalnızca istemeden betik çalıştırmayı zorlaştırır. Güvenlik için betikleri sürüm kontrolünde tutun, imzalayın ve en düşük yetkiyle çalıştırın.
- Etiketler active directory, windows server
- Teknoloji
- PowerShell 5.1/7, WinRM, PowerShell Remoting, ActiveDirectory modülü, Task Scheduler, gMSA
- Konu
- Tekrarlanan sunucu işlerinin betiklenmesi
- Seviye
- Orta
- Ön koşullar
- Temel PowerShell sözdizimi bilgisi
- Etki alanına üye Windows Server ortamı
- RSAT ActiveDirectory modülü
Sistem Destek