Dosya sistemi işleri
Dosya sistemi temel komutları olan cd, dir, del, mkdir gibi komutları aynen Powershell'de de kullanabiliyoruz. Bunlar alias'lar aracılığıyla oluyor. Ama aslında arka tarafta komut satırı penceresinin iç komutlarından başka komutlar çalışıyor.
C:\> dir
PS C:\> Get-ChildItem
C:\> cd
PS C:\> Set-Location
C:\> del
PS C:\> Remove-Item
C:\> mkdir
PS C:\> New-Item -ItemType Directory
Bunlara ek olarak örneğin tüm alt klasörlerde bulunan ve isminde fatura geçen dosyaları bulmak için
C:\> dir *fatura* /s
eşdeğeri
PS C:\> dir -Include *fatura* -Recurse
Hatta daha da fazlasını yapıp içinde fatura geçen dosyaların son 1 ayda oluşturulanlarını bulmak için ise
PS C:\> dir -Include *fatura* -Recurse | ? {$_.CreationTime -gt (Get-Date).AddMonths(-1)} | select CreationTime, LastWriteTime, Fullname
kullanılabilir. -Include anahtarı bazen garip bir şekilde istediğim gibi sonuç vermiyor. Bu durumda -Filter anahtarı faydalı olabiliyor. Tek yapılacak -Include'u silip yerine -Filter eklemek. Duruma göre tırnak içine almak gerekebilir.
En çok ihtiyaç duyduğum başka bir şey ise içinde belli bir kelime veya karakter kümesi geçen belli tipte uzantıya sahip dosyaları bulmak. Bunu klasik komut satırında şu şekilde yapıyordum:
C:\> findstr /s /i "admin" *.log
Bunun eşdeğeri de Select-String cmdlet'i. Alias'ı ise sls:
PS C:\> dir *.log -Recurse | sls -Pattern "admin"
findstr.exe alt klasörleri de kapsama alabilecek /s anahtarına sahip. Select-String (sls) cmdlet'inin böyle bir yeteneği yok ama Get-ChildItem (dir) cmdlet'inin çıktısını ona yönlendirerek bu ihtiyacı karşılayabiliyoruz. Eğer alt klasörler değil de sadece mevcut klasördeki bazı dosyalar içinde arama yapacaksak dir (Get-ChildItem) komtuna ihtiyaç yok. Doğrudan sls (Select-String) kullanabiliriz:
PS C:\> sls -Path C:\*.log -Pattern "admin"
Select-String cmdlet'i varsayılan olarak küçük/büyük ayrımı yapmaz (case insensitive). Özellikle küçük/büyük harf ayrımı olmasını isterseniz -CaseSensitive parametresini kullanmalısınız.
Komut satırından yeni dosya oluşturmak için New-Item cmdlet'i kullanılabilir. New-Item hem dosya, hem klasör, hem de başka sağlayıcıların yeni öğelerini yaratmak için kullanılabilir. Varsayılan değeri File (dosya)dır.
PS C:\>New-Item -Path D:\klasor1 -ItemType file -Name dosya1.txt
Dosya veya klasör ismini değiştirmek için Rename-Item kullanılabilir.
PS C:\>Rename-Item -Name dosya.log -NewName dosya.txt
Ancak Path parametresi wildcard desteklemez. Bunun için toplu dosya isim değiştirme işlemlerini şunun gibi yapmak gerekir:
PS C:\>Get-ChildItem *.log | Rename-Item -NewName {$_.Name -replace ".log", ".txt"}
Ağ sorun giderme
Komut satırının meşhur ping komutu harici bir komut olduğu için Powershell'de ping çalışıyor. Ama bunun yerine başka bir alternatif komut daha var.C:\> ping 192.168.1.1
Pinging 192.168.1.1 with 32 bytes of data:
Reply from 192.168.1.1: bytes=32 time<1ms TTL=128
Reply from 192.168.1.1: bytes=32 time<1ms TTL=128
Reply from 192.168.1.1: bytes=32 time<1ms TTL=128
Reply from 192.168.1.1: bytes=32 time<1ms TTL=128
Ping statistics for 192.168.1.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
PS C:\> Test-Connection -Computarname 192.168.1.1 Source Destination IPV4Address IPV6Address Bytes Time(ms) ------ ----------- ----------- ----------- ----- -------- MET8 192.168.1.1 192.168.1.1 32 0 MET8 192.168.1.1 192.168.1.1 32 0 MET8 192.168.1.1 192.168.1.1 32 0 MET8 192.168.1.1 192.168.1.1 32 0
Bu bildiğimiz ICMP ping.exe'nin karşılığı. Aynı ping.exe'de olduğu gibi varsayılan olarak 32 byte'lık paketler gönderiyor. Varsayılan olarak 1 saniye bekliyor, varsayılan olarak 4 paket gönderip duruyor. Sırasıyla bu parametreleri değiştirmek için -BufferSize, -Delay ve -Count kullanmak gerek.
Ayrıca ICMP ile değil de, TCP ile herhangi bir portu denemek istersek de
PS C:\> Test-NetConnection -ComputarName server01 -Port 21
kullanabiliriz. Bunun eşdeğeri klasik komut satırında yoktu. Bunun yerine psping veya benzer uygulamaları kullanıyorduk. tracert komutunun eşdeğeri olarak Test-NetConnection'ı -TraceRoute parametresi ile birlikte kullanabilirizi
PS C:\> Test-NetConnection -TraceRoute google.com
Bilgisayarda hangi ağ aygıtları var görmek istersek:
PS C:\> Get-NetAdapter Name InterfaceDescription ifIndex Status MacAddress LinkSpeed ---- -------------------- ------- ------ ---------- --------- Ethernet Broadcom NetXtreme... 4 Up XX-XX-XX-XX-XX-XX 1 Gbps Wi-Fi Intel(R) Centrino ... 3 Discon. XX-XX-XX-XX-XX-XX 0 bpsBuradan bir arayüzün IP adresini bulmak istersek (örneğin Ethernet cihazı) ifIndex sütunundaki arayüz endeksini alıp aşağıdaki komuta yazarak IP adresini öğrenebiliriz.
PS C:\> Get-NetIPAddress -InterfaceIndex 4 IPAddress : 192.168.1.5 InterfaceIndex : 4 InterfaceAlias : Ethernet AddressFamily : IPv4 Type : Unicast PrefixLength : 16 PrefixOrigin : Manual SuffixOrigin : Manual AddressState : Preferred ValidLifetime : Infinite ([TimeSpan]::MaxValue) PreferredLifetime : Infinite ([TimeSpan]::MaxValue) SkipAsSource : False PolicyStore : ActiveStore
PS C:\> Get-NetTCPConnection -RemotePort 443
Hizmetler
Yerel bilgisayardaki hizmetlerin bir listesini almak için komut:PS C:\> Get-Service
veya kısaca
PS C:\> gsv
yeterli. Ama hayat her zaman bu kadar kolay olmuyor. İlgilendiğimiz sadece DHCP client hizmeti ise şu şekilde bir komut ile durumunu sorgulayabiliriz:
PS C:\> gsv dhcp Status Name DisplayName ------ ---- ----------- Running Dhcp DHCP Client
Bu hizmeti tekrar başlatmak için boru karakteri ile Get-Service cmdletinin yukarıdaki çıktısını Restart-Service cmdlet'ine yönlendirebiliriz.
PS C:\> gsv dhcp | Restart-Service
Bazen de adını tam bilmediğimiz bir hizmetin durumunu öğrenmek isteriz. Örneğin "Bit Locker Drive Encryption Service"in kısa servis adını bulmak için şunu yapabiliriz:
PS C:\> gsv | select DisplayName, Name, Status | sls "bit"
@{DisplayName=BitLocker Drive Encryption Service; Name=BDESVC; Status=Stopped}
@{DisplayName=VMware USB Arbitration Service; Name=VMUSBArbService; Status=Running}
2 tane hizmet döndü, bunların ilki bizim aradığımız (daha temiz bir çıktı için gsv | out-string -stream | sls "bit" kullanılabilir). Kırmızı ile belirttiğim kısa hizmet adının hemen devamında da Status = Stopped olarak gözüküyor. Bunu tekrar başlatmak istersek
PS C:\> Start-Service BDESVC
dememiz yeterli.
(04.01.2018 düzeltme: daha da kısa olarak aynı şeyi gsv -Disp *bit* ile de yapabiliriz)
Sadece çalışan servisleri başlatmak için kullanabileceğimiz bir parametresi yok Get-Service cmdlet'inin. Bunun yerine Get-Service'in çıktısını Where-Object cmdlet'ine yönlendirerek sadece çalışanları süzebiliriz:
PS C:\> gsv | ? {$_.Status -eq "Running"}
Eğer bu işi yerel makinede değil de uzaktaki bir makinede yapmak istiyorsak Get-Service cmdlet'ine -ComputerName parametresi ile uzak makine adını belirmek gerek.
PS C:\> gsv -Computername server01| ?{$_.Status -eq "Running"}
Windows Olayları
En sık kullanılan araçlardan biri de Windows Olaylarıdır. Örneğin sistem olay günlüğüne bakmak için şu cmdlet'i kullanabiliriz:PS C:\> get-eventlog -LogName system
Tabi bu binlerce kayıt dönebilir. Bunun yerine en yeni 10 olaya
PS C:\> get-eventlog system -Newest 10
ya da son 1 saatte meydana gelen olaylara bakmak isteyebiliriz:
PS C:\> get-eventlog system -After (Get-Date).AddHours(-1)
Eğer belli bir Event ID'ye sahip olayları süzmek isterseniz bu noktada yine Where-Object'e başvurmak gerek.
PS C:\> Get-Eventlog -LogName system -Newest 10 | Where-Object {$_.EventID -eq 7040}
Where-Object'e başvurmadan doğrudan Get-Eventlog tarafından süzme işleminin yapılabiliyor olması güzel olurdu, ama olmamış. Bunun ne dezavantajı var? Yukarıdaki örnekte öncelikle son 10 olayı görmek istiyor, sonrasında da bu olayların içinde Event ID'si 7040 olanları seçiyoruz. Bu durumda dönen olay sayısı 10 da olabilir, 0 da olabilir. Yani Event ID'si 7040 olan son 10 olayı almak istersek bu sefer olayın sırasını değiştirmek lazım:
PS C:\> Get-EventLog -LogName system | Where-Object {$_.EventID -eq 7040} | Select-Object -First 10
Ancak bu da nispeten ilk duruma göre çok daha fazla uzun sürecek. Çünkü Get-Eventlog çalışmaya başlayınca en yeni olaylardan başlayarak olayları getirir. Belli bir ölçüt belirtilmişse o ölçüte göre (son 5 olay, son 1 saatte olan olaylar, belli bir kaynaktan gelenler vs.) göre işlem yapar. Ancak son örnekteki gibi bir ölçüt yoksa tüm olayları tarar, ve sonrasında bunların içinden süzme işlemi yapar. Bu da hem daha fazla işlemci hem de daha fazla bellek kullanımını gerektirir.
Alternatif olarak Get-EventLog cmdlet'i yerine Get-WinEvent cmdlet'i kullanılabilir. 7040 olay kimliği için son 10 olayı aşağıdaki şekilde çekebilriz:
PS C:\> Get-WinEvent -FilterHashTable @{LogName=System;ID=7040} -MaxEvents 10
Veya son 1 saat içinde gerçekleşen tüm 7040 olaylarını görmek için
PS C:\> Get-WinEvent -FilterHashTable @{LogName=System;ID=7040;StartTime=(Get-Date).AddHours(-1)}
Birden fazla ID'yi virgüllerle ayırarak yazabiliriz. StarTime gibi EndTime gibi bir son tarih-saat bilgisi de verilebilir. FilterHashTable ile kullanılabilecek bazı alanlar
Key name Value data type Accepts wildcard characters?
LogName <String[]> Yes
ProviderName <String[]> Yes
Path <String[]> No
Keywords <Long[]> No
ID <Int32[]> No
Level <Int32[]> No
StartTime <DateTime> No
EndTime <DataTime> No
UserID <SID> No
Data <String[]> No
* <String[]> No
Görüleceği gibi wildcard'lar sadece LogName ve ProviderName için kullanılabiliyor. Keyword gibi alanlar olayın ayrıntısında anahtar kelime araması yapmak için değil. Bu alan için veri tipinin Long[] olduğuna dikkat etmek gerek. Sadece hataları listelemek için Level=2, uyarılar için Level=3 ve nihayet bilgi seviyesindeki olaylar için Information=4 kullanılabilir.
Kayıt Defteri
Windows Kayıt defteri ile uğraşmak nispeten komut satırına göre daha kolaydır. Yolunu bildiğiniz bir kayıt defteri konumunu sanki dosya sisteminde bir konumda çalışıyormuş gibi cd (Get-ChildItem) cmdlet'iyle görebilirsiniz.PS C:\> dir HKLM:\Software\Microsoft\Windows\CurrentVersion\Run
Üstelik de her adımda tab ile tamamlama imkanıyla.
Get-ChildItem ile gezilebilecek yerler dosya sistemi ile kayıt defterinden ibaret değil. Bu tip nesnelere PowerShell Drive deniyor. Tüm PSDrive sürücülerinin listesi için
PS C:\> Get-PSDrive Name Used (GB) Free (GB) Provider Root ---- --------- --------- -------- ---- Alias Alias C FileSystem C:\ Cert Certificate \ D FileSystem D:\ Env Environment Function Function S FileSystem \\server\paylasim HKCU Registry HKEY_CURRENT_USER HKLM Registry HKEY_LOCAL_MACHINE WSMan WSMan
gibi bir sonuç elde ederiz. Bu da demektir ki örneğin alias'lar hakkında bilgi için Get-Alias ve Get-Help'in dışında doğrudan
PS C:\> cd Alias:
komutunu kullanıp dir ile tüm alias listesini alabiliriz.
Kayıt defteri konusuna gelelim. HKLM\Software\Microsoft\CurrentVersion\Run altındaki değerleri sorgulayalım:
PS C:\> cd HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\run
PS C:\> dir
Burada bazı değerler olmasına rağmen içerik gözükmedi. dir (Get-ChildItem) sadece alt anahtarları listeler. Değerleri görmek için
PS C:\> Get-ItemProperty . Apoint : C:\Program Files\DellTPad\Apoint.exe PSPath : Microsoft.PShell.Core\Registry::HKEY_LOCAL_MACHINE\... PSParentPath: Microsoft.PShell.Core\Registry::HKEY_LOCAL_MACHINE\... PSChildName : run PSDrive : HKLM PSProvider : Microsoft.PowerShell.Core\Registry
kullanabiliriz (ekrana sığsın diye kısalttım). Burada Run anahtarı altında yer alan değer Apoint'ti.
Yeni Registry değeri yaratmak için
PS C:\> New-Item Adobe
ve bu alt anahtarın altında kayıt defteri değerleri yaratmak için ise
PS C:\> New-ItemProperty -Path . -Name "Disable" -Type DWord -Value 1
kullanabiliriz. Aynı şekilde alt anahtarları silmek için Remove-Item, değerleri silmek için ise Remove-ItemProperty kullanılmalı.
Ortam Değişkenleri
Ortam değişkenleri de bir sistemin işleyişinde önemli yere sahip. Önceki başlıkta Get-PSDrive ile gezinmeye uygun nesneleri listelerken Env de çıkmıştı. Yani ortam değişkenlerinden PATH'i görmek içinPS C:\> cd ENV:
PS C:\> dir Path
Name Value
---- -----
Path C:\ProgramData\Oracle\Java\javapath...
kullanmak mümkün. Ayrıca
PS C:\> $ENV:Path
de aynı işi yapar. Daha okunaklı bir liste için
PS C:\> ($Env:Path).Split(";")
yapabiliriz. Bu listeye örneğin C:\Scripts klasörünü eklemek istersek yapmamız gereken
$Env:Path += ";C:\Scripts"
Veya bunu tekrar silmek için
$Env:Path = $Env:Path.Replace(";C:\Script","")
yapabiliriz. Ama bu ortam değişkenini kalıcı olarak değiştirmez. Kalıcı yapmak için
[Environment]::SetEnvironmentVariable( "Path", $env:Path, [System.EnvironmentVariableTarget]::Machine )
şeklinde sistem genelinde değişiklik yapan yordam çağrılmalı.
Son olarak bazı durumlarda uyumsuz veri tiplerinin gizemini çözmek için kullanılabilecek cmdlet Get-Member'a örnek vereyim:
PS C:\> $Env:Path | Get-Member
Uzun bir liste verecek. İlk sırada yer alacak
TypeName: System.String
bizim için anahtar. Örnek bir kullanım için tüm alias'lar içinde hizmetlerin yönetimi için kaç alias yaratıldığını bulmak isteyelim.
PS C:\> dir Alias:
komutu ile tüm alias'ları listeleyebiliriz. Ama acaba bunların kaçının içinde "service" geçiyor. Select-String (sls) cmdlet'iyle içinde service geçenleri bulmaya çalışalım:
PS C:\> dir Alias: | sls "service"
Hiçbir şey dönmedi. Neden? Çünkü adından da anlaşılacağı gibi Select-String cmdlet'i sadece string veri tipi üzerinde çalışır. Sebebi dir Alias: komutunun string veri tipi dönmemesi olabilir mi? Bakalım:
PS C:\> dir Alias: | Get-Member
TypeName: System.Management.Automation.AliasInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
diye uzayan bir çıktı üretir. İlk satırda yazan
TypeName: System.Management.Automation.AliasInfo
bizim için önemli. Yani string veri tipi dönmemiş. Bir array döndüğü için array'in ilk elemanının tüm özelliklerini (property) yazalım:
PS C:\> (dir Alias:)[0] | fl *
DisplayName : % -> ForEach-Object
CommandType : Alias
Definition : ForEach-Object
ReferencedCommand : ForEach-Object
ResolvedCommand : ForEach-Object
Burada çok şaşırtıcı olmayan "DisplayName" adında bir alan var. Bu alanın tipini kontrol edelim:
PS C:\> (dir Alias:)[0].DisplayName | Get-Member
TypeName: System.String
String'i bulduk. Demek ki Select-String'in girişi bu alan olmalı.
PS C:\> (dir Alias:).DisplayName | sls "service"
gsv -> Get-Service
sasv -> Start-Service
spsv -> Stop-Service
Sonuçta 3 alias olduğunu gördük. İlla ki powershell saysın dersek:
PS C:\> (dir Alias:).DisplayName | sls "service" | Measure
Count : 3
Average :
Sum :
Maximum :
Minimum :
Property :
Hiç yorum yok:
Yorum Gönder