12.10.2017

Günlük ihtiyaçlar için Powershell

Bu yazı, standart komut satırı araçlarının Powershell eşdeğerlerini listelemeyi amaçlıyor. Aşağıda önce komut satırı çözümünü, sonrasında da Powershell eşdeğerini yazacağım.

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

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.

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.

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. 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.

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 binlerde 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.

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çin

PS 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: