25.10.2017

nmap

1 Eylül 2017 itibariyle nmap 20 yaşını dolduran proje. Her türlü çok faydalı.

Karışımızda tek bir bilgisayar (genel anlamda herhangi bir ağ cihazı olabilir, ama kısaca bilgisayar veya cihaz diyelim) var, IP adresi 192.168.1.1 olsun ve bu bilgisayarın sık kullanılan portlar üzerinden bir taramasını yapmak istiyoruz. Kullanacağımız komut:

nmap 192.168.1.1

Starting Nmap 7.31 ( https://nmap.org ) at 2017-10-24 09:05 Turkey Standard Time
Nmap scan report for 192.168.1.1
Host is up (0.027s latency).
Not shown: 997 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
23/tcp open  telnet
80/tcp open  http
MAC Address: XX:YY:ZZ:WW:QQ:AA (üretici)

Nmap done: 1 IP address (1 host up) scanned in 2.16 seconds


gibi bir sonuç döner. Bir çok güzel bilgi var. 1000 tane port taramış, 997 tanesinin kapalı olduğunu, 3 tanesinin ise açık olduğunu söylüyor: 22, 23 ve 80. En altta gizlediğim MAC adresi var, yanında parantez içinde de üretici bilgisi yer alıyor. Birden fazla cihazı isim veya IP adreslerini boşlukla ayrılmış bir şekilde aynı satıra yazarak da taratabiliriz. IP aralığı vermek için 192.168.1.1-10 veya tüm oktet yerine * karakterini kullanarak 192.168.1.* veya CIDR notasyonu ile 192.168.1.1/24 de yazabiliriz.

Genel olarak taramanın iki aşaması var; ilk aşama cihaz keşfi (host discovery). Bu aşamada verilen IP aralığındaki açık ve taranabilir cihaz listesi çıkartılıyor, açık olduğuna dair hiçbir iz olmayan IP adreslerinin portlarını tarayarak vakit kaybetmemek için. İkinci aşama port taraması (port scanning). Bu aşamada da hedef bilgisayarların açık olan portlarını bulmaya çalışıyor. Sadece cihaz keşfi yapıp, port taraması yapmamak için -sn anahtarını, tam tersi durumda cihaz keşfi yapmadan doğrudan verilen tüm IP adreslerini port taramasına sokmak için -Pn anahtarını kullanabiliriz.

Cihaz Keşfi

Port taramasını tamamen atlayıp sadece ping taraması gerçekleştirmek için:

nmap -sn 192.168.1.*

Sadece belli bir aralıktaki cihazların ters DNS sorgularını yapıp toplam sayıyı almak için (bilgisayarlara hiçbir paket gönderilmeden)

nmap -sL 192.168.1.*

SYN flag set edilmiş TCP paketi ile ping yapmak için (port taramasız):

nmap -sn -PS 192.168.1.*

SYN biti 1 olan bir paket alındığında, eğer o portu dinleyen bir hizmet yoksa RST biti 1 olan bir paket ile cevap verilir. Eğer dinleyen bir hizmet varsa da hedef makine bir sonraki aşamaya geçerek SYN/ACK bitleri 1 olan bir paket ile cevar verir. Bu da yine karşıdaki cihazın açık olduğunu anlamamıza yarar.

ACK flag set edilmiş TCP paketi ile ping yapmak için (port taramasız):

nmap -sn -PA 192.168.1.*

ACK biti 1 olan bir pakette ise var olan bir TCP bağlantısında alınan veriye ait alındı cevabı gönderiliyormuş gibi yapılır. Bu cevabı alan hedef makine ise RST biti 1 olan bir paket ile cevap verir ki bu da aynı şekilde hedef makinenin açık olduğunu gösterir.

Yukarıdaki iki yöntem varsayılan olarak TCP 80 portunu kullanır. Bu durumu değiştirmek için komut satırında -p20 gibi bir port belirtebiliriz.

UDP taraması yapmak için (port taramasız):

nmap -sn -PU 192.168.1.*

varsayılan olarak UDP taramasında 40125 portu kullanılır, kullanılan bir porta denk gelmesi için. Kullanmayan bir porta UDP paketi gönderildiğinde ICMP port erişilemiyor cevabının gönderilir. Bu da karşıdaki bilgisayarın açık olduğunu gösterir. Kullanımda bir UDP portuna denk gelirsek hiçbir cevap dönülmez. Bu sebeple varsayılan olarak 40125 gibi kullanılma ihtimali az olan bir port seçilmiş.

Bir de SCTP kullanarak yukarıdaki denemenin yapılması var:

nmap -sn -SY 192.168.1.*

Denemeleri yaparken dikkat edilecek bir konu; yerel ağdaki bir hedefi tarıyorken bir de WireShark'ta gönderilen paketleri inceliyorsanız sadece ARP protokolünün kullanıldığını, ne TCP SYN ne de ACK kullanıldığını görünce şaşırabilirsiniz. Bu durum yerel ağdaki cihazların açık olduğunu ARP ile anlamanın daha kolay olmasından kaynaklanıyor. nmap bu kolay yöntemi kullanıyor. ARP'yi kapatmak için komut satırından --disable-arp-ping 'i kullanabilirsiniz, şöyle:

nmap -sn -PS 192.168.1.* --disable-arp-ping

Tam tersine, yerel ağdaki cihazları sadece ARP sorgularıyla tespit etmek istiyorsak ARP ping kullanmalıyız:

nmap -sn -PR 192.168.1.*

ARP protokolü düşük TCP stack'inde düşük seviyede çalışan bir protokoldür. İşletim sisteminin güvenlik duvarı ile "genelde" engellenmezler. Basit olarak gönderilen "Kim 192.168.1.5 adresine sahip?" sorgusuna, bu adrese sahip cihaz tarafından cevap verilir. Bunu aslında 192.168.1.5 adresine ping atıp daha sonra ARP cache'ine bakarak da bulabiliriz. Ama nmap'in bu işi işletim sisteminin algoritmalarına kıyasla, çok sayıda hedef cihaz üzerinde daha optimize bir şekilde yaptığı belirtilmiş.

Port Taraması

nmap'in -P ile başlayan anahtarları cihaz keşfi ile ilgili olanlardı. Port taraması ile ilgili olanlar ise -s ile başlar.

Yine SYN biti 1 olan bir paket ile port taraması yapmak için

nmap -sS -p80 192.168.1.1

SYN paketi gönderip gerisini getirmeden bağlantıyı sonlandırmak için işletim sistemi tarafından sunulan standart ağ rutinlerinin dışında özel paketler göndermek gerekir. Bu da root/administrator yetkisi ister çoğu durumda. Bu duruma alternatif işletim sisteminin standart rutinleri ile işi gerçekleştirmek için TCP Connect taraması tercih edilebilir.

nmap -sT -p80 192.168.1.1

SYN taraması çoğu durumda loglara girmez, dikkat uyandırmaz. Ama çok sayıda TCP Connect taraması loglara girer ve dikkat uyandırır. Dahası yavaştır ve aynı bilgiyi elde etmek için daha fazla paket gönerilmesini gerektirir. Ama mecbur kalınınca kullanılabilir.

UDP kullanan portlar üzerinden tarama yapmak için ise

nmap -sU 192.168.1.1

Cihaz keşfini atlayıp sadece 53 UDP portunu kontrol etmek istersek

nmap -Pn -sU -p53 192.168.1.1

SCTP ile port taraması yapmak için -sY kullanılablir. Şu sayfada çok faydalı bir yöntem olarak vurgulanmış.

nmap -sY 192.168.1.1

Cihaz keşfinde kullanılan ACK bitini port taramasında da kullanabiliyoruz. Ama burada durum biraz daha farklı. -sA ile TCP ACK scan yapmak mümkün. Ama bu taramayla portların tam durum bilgisini edinmek mümkün değil. Daha çok firewall kurallarını tahmin etme, stateful mu değil mi öğrenmek için kullanılabilir.

Bunun dışında TCP Null (-sN), TCP FIN (-sF) ve Xmas (-sX) taramaları var, ama kullanım alanları biraz daha kısıtlı.

Hedef bilgisayarın verdiği cevaplara göre hangi işletim sistemine sahip olduğunu tahmin edebiliriz:

nmap -O 192.168.1.1

Hedef bilgisayarın bir güvenlik duvarı ile korunup korunmadığını bulmak için

nmap -sA 192.168.1.1

Son olarak port bazında dönülen open, closed ve filtered durumlarına açıklama getireyim. Bir port açıksa ve gönderilen örneğin SYN paketine SYN veya SYN/ACK ile cevap veriyorsa port open olarak listelenir. Bağlantıya karşılık RST ile cevap veriyorsa port kapalı olarak listelenir. Gönderilen pakete hiç cevap gelmiyorsa filtered olarak görülür.

[1] https://nmap.org/book/man
[2] https://nmap.org/book/man-host-discovery.html
[3] https://nmap.org/book/man-port-scanning-techniques.html

23.10.2017

Wayland mi X mi kullanıyoruz nasıl anlarız?

Linux veya benzeri işletim sistemlerinin grafik arayüz için kullandıkları X Windowing System'in günlük ihtiyaçları karşılayamaması sebebiyle Waylan adında bir projeye başlandı. Bazı dağıtımlar hala X kullanırken bazıları Wayland'a geçiş yaptı.

Kullandığımız dağıtımın hangisini kullandığını nasıl anlarız sorusuna bulduğum yanıtlar şöyle:

1. Yöntem:
Terminalden önce mevcut oturum kimliğimizi (session ID) bulalım:

$ loginctl
    SESSION       UID    User       SEAT
          1      1000    metin      seat0

Dikkat edilecek yer, SESSION başlığının altında kalan sayı. Bizi durumumuzda 1. İkinci adımda bu sayıyı kullanarak şu satırı yazalım (küçük büyük harf duyarlı):

$ loginctl show-session 1 -p Type
Type=X11

Hala X11 kullanıyormuşuz.

2. Yöntem
$ echo $XDG_SESSION_TYPE
x11

sonuç x11 veya wayland olarak belirtilir. Benim X kullandığı çıktı.

3. Yöntem
$ ps aux | grep gnome-shell

Eğer sonuçların arasında --wayland görünüyorsa Wayland kullanıyoruz. Benim sistemimde bu

metin 1877 0.0 0.0  118520   976  pts/0  S+  08:09  0:00 --color=auto  gnome-shell

gibi birşey çıktığı için X kullanıyorum.

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.

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 :                                                

Powershell'e giriş

Windows'da komut satırının yeteneklerinin günümüz beklentilerinin altında kalmasına çözüm olarak ortaya çıkan Powershell faydalı ve kullanışlı bir framework haline geldi. .Net altyapısı üzerine inşa edilen sistem her yeni sürümde daha faydalı işlevler sunuyor

Powershell komutlarına cmdlet deniyor. Bir fiil ve ismin tire işareti ile birleşiminden oluşuyorlar. Örneğin çalışan süreçlerin listesini almak için kullanılacak komut (cmdlet):

Get-Process
Ama her seferinde bu kadar uzun komutlar girmemek için kısaltma amaçlı "alias"lar eklenmiş. Her seferinde Get-Process yazmak elbette mümkün, ama kısaltmak isterseniz

gps
veya
ps
de aynı işi yapıyor. Bu alias elbette linuxtaki eşdeğeri ps komutundan geliyor. Ama linux eşdeğerinden farklı olarak tamamen nesne yönelimli (object oriented). Tüm çalışan süreçlerin listesini değil de sadece svc ile başlayan süreçlerin listesini görmek istersek yapılacak
ps svc*
yazmak. Bunun sonucunda aşağıdaki gibi bir çıktı üretecek:

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    844      30    19016      21172    90             232 svchost
   1005      37   112316     114080   190             396 svchost
   2163      71    72416      72612   349             412 svchost
    652      34    12444      20520   145             452 svchost
    527      19     8504      14744    82             756 svchost
    547      18     6752      10376    71             796 svchost
   1250     183    24952      28980  1309            1240 svchost
    325      19     3396       8688    54            1508 svchost
    489      38    27524      28188   116            1532 svchost
    108      10     3316       3040    42            1844 svchost
     55       6      712       1224    21            2036 svchost
    369      17     5584      10000    91            2044 svchost
     53       6      712       1280    21            2088 svchost
    100       8     1312       2224    24            2136 svchost
    165      14     4176       5092    48            2568 svchost
    145      11     2148       5920    43            5968 svchost


Buradaki sütünların açıklamaları [1] ve [2] de var.
Örneğin handle sayısı 1000'den fazla olan ve svc ile başlayan süreçleri listelemek için

ps svc* | ? {$_.Handles -gt 1000}

yazmak yeterli. Bu komutun kısaltılmış hali. Uzun uzun alias kullanmadan yazmak istersek komut şöyle olurdu:
Get-Process -Process svc* | Where-Object {$_.Handles -gt 1000}
Soru işareti (?) Where-Object cmdlet'inin bir alias'ı. Get-Process cmdlet'inin varsayılan parametresi de Process olduğu için ayrıca -Process yazmaya gerek yok. Önemli olan kısmı boru karakterinden (|) sonrası. Komut satırında olduğu gibi burada da boru karakteri bir komutun çıktısını diğer komuta giriş olarak veriyor. svc ile başlayan süreçlerlerin listesini al, Where-Object komuduna ver. O da bunları bir döngüye soksun (küme parantezleri sanal bir for döngüsü gibi), sadece Handles değeri 1000'den büyük olanları çıkış olarak üretsin. Burada $_ sanal for döngüsündeki döngü değişkeninin yerine geçiyor. Döngünün her adımında nesnenin Handles özelliğini alıp -gt ile "büyüktür" (greater than) işlemine tabi tutuyor. Sonucunda da şu çıkıyor:

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1008      38   114932     113968   193             396 svchost
   2226      71    75344      73328   347             412 svchost
   1245     182    24888      28940  1308            1240 svchost


Tam da istenen bu. Powershell bunun için güzel :)

Hatta bunları da Working Set değerine göre azalan şekilde sıralamak istersek yazılması gereken bir boru karakteri daha var:
ps svc* | ? {$_.Handles -gt 1000} | sort WS -Desc
Bu komutu da uzun uzadıya yazmak istersek
Get-Process -ProcessName svc* | Where-Object {$_.Handles -gt 1000} | Sort-Object -Property WS -Descending
olurdu. Tabloyu çok karmaşık bulursanız, sadece Handles ve Working Set değerlerni süreç isim ve ID'leriyle görmek isterseniz bu alanlardan sadece bazılarını select ile seçmeniz gerekir:
ps svc* | ? {$_.Handles -gt 1000} | sort WS -Desc | select Id, ProcessName, WS, Handles

Bu noktadan sonra uzunlarını yazmaya gerek yok bence.

Hala eklenebilecek şeyler var. Working Set sütununun sayısal biçimlendirmesini beğenmeyenler binlik ayraç kullanmak isteyebilir. Bu durumda
ps svc* | ? {$_.Handles -gt 1000} | sort WS -Desc | select Id, ProcessName, @{N="WorkingSet";E={"{0,13:N0}" -f $_.WS}}, Handles

yazılabilir. Sonuç şu şekilde olur:

 Id  ProcessName       WorkingSet                          Handles
 --  -----------       ----------                          -------
 396 svchost           114.790.400                           1005
 412 svchost            72.474.624                           2173
1240 svchost            29.532.160                           1245


Çıkışı buraya sığdırmak için boşlukları sildiğimi itiraf etmeliyim. Ama bunu gerek kalmadan sonuç üretmek için de Format-Table * -Autosize ekleyebilirdim. Yani:
ps svc* | ? {$_.Handles -gt 1000} | sort WS -Desc | select Id, ProcessName, @{N="WorkingSet";E={"{0,13:N0}" -f $_.WS}}, Handles | ft -AutoSize
Sonuç şöyle olurdu:

  Id ProcessName WorkingSet    Handles
  -- ----------- ----------    -------
 396 svchost       114.221.056    1005
 412 svchost        72.462.336    2173
1240 svchost        29.532.160    1247


Temiz ve güzel.

9.10.2017

Fedora'da dnf kullanımı

Fedora'da yum'ın yerini alan dnf gayet pratik. Ama özetlemek için birkaç önemli noktayı yazmak istedim, biraz da apt ile kıyaslayarak (// işaretinden sonrası Ubuntu için).

Repository'leri güncellemek

# dnf check-update  // apt update
Kurulu bütün paketleri güncellemek
# dnf update // apt upgrade
Tek bir paketi güncelleme
# dnf update firefox // apt upgrade firefox
Veya daha da öncesinde paket kurmak
# dnf install firefox // apt install firefox
Paketi kaldırmak
# dnf remove firefox // apt remove firefox
Bazen log dosyaları vs ile birlikte programın tüm artıklarından kurtulmak gerekir. Bu işin dnf'te karşılığı yok.
 # --------- // apt purge firefox (veya apt remove --purge firefox)
Kurulu paketi tekrar kurmak
# dnf reinstall firefox  //  apt reinstall firefox
Başka bir programın bağımlılığı olarak kurulmuş ama şu anda ihtiyaç duyulmayan paketleri kaldırmak için
# dnf autoremove // apt autoremove
Güncellenebilir (veya kurulu) olan paketlerin listesini almak için
# dnf list --upgrades (--installed) // apt list --upgradable (--installed)
Bir paket aramak
# dnf search (all) firefox // apt-cache search firefox
Bir paket hakkında ayrıntılı bilgi almak
# dnf info firefox // apt show firefox
Kurulu ve depolardaki sürüm hakkında bilgi almak
# dnf info firefox // apt-cache policy firefox
Bir dosyayı hangi paket kurdu
# dnf provides <dosya_adi> //  dpkg -S <dosya_adi> (veya # apt-file search <dosya_adi>
Komut geçmişini incelemek
# dnf history // # less /var/log/apt/history.log [bkz. 2]
Ubuntu ile aralarındaki bir küçük fark da örneğin dnf update sonrasında emin misiniz sorusunun cevabının varsayılan olarak "hayır (H)" olması. Ubuntu'da bu varsayılan olarak evetti.

[1] https://www.digitalocean.com/community/tutorials/package-management-basics-apt-yum-dnf-pkg
[2] https://askubuntu.com/questions/21657/how-do-i-show-apt-get-package-management-history-via-command-line

27.09.2017

takas bölümünü etkinleştirmek

Mevcutta bir linux kurulumuna sahip bir makineye ikinci bir linux yüklüyorum. İkinci linux için partition hazır. Ama takas (swap) bölümünü diğer linux kurulumu ile paylaşmak istiyorum. Çok yüksek güvenlikli bir sistem olsaydı bunu yapmamak lazım. Ama kullandığım öyle bir sistem değil ve bunu yapmak mümkün.

İkinci linuxun kurulumu sırasında sda7'yi / (kök) olarak mount etmeyi seçtim, ama swap için bir partition seçmedim. Seçersem bu partition'ı formatlayacak, ve diğer linuxun bu disk bölümüne bağlantısı kopacak.

İkinci linuxun kurulumu tamamlandıktan sonra

$ free
          total     used      free    shared    buff/cache   available
Mem:     1828852    796260    445196   141164     587396        627628
Swap:       0          0         0

yazarak sistemin herhangi bir swap kullanmadığını (Swap satırındaki değerler tümü 0) doğruladım. Mevcut sistemdeki takas bölümünün (swap partition) hangisi olduğunu bulmak için fdisk'i kullandım:

$ sudo fdisk -l

Bu komutun çıktısında türü Linux takas olarak listelenen tek bölümün sda8 olduğunu gördüm. Birinci kurduğum linux zaten bu bölümün yapılandırmasını yaptığı için

$ sudo mkswap /dev/sda8

yapmama gerek kalmadı. Eğer ilk defa yapılandırıyor olsaydım bu komutu kullanmam gerekecekti. Bölüm hazır olduğu için doğrudan

$ sudo swapon /dev/sda8
Komutu ile takas alanını etkinleştirdim. Bunu doğrulamak için

$ free
           total        Used      free     Shared   buff/cache       available

Mem:       1828852     796260    445196    141164   587396             627628
Swap:      3771388         0    3771388


Komutunu kullandım. Son satırda total sütununda swap'ın sıfırdan farklı bir değerde olması yeterli.

Yalnız bu, bir sonraki açılışta takas bölümünün tekrar bağlanacağını garantilemiyor. Bunu garantilemek için /etc/fstab dosyasına ilgili girişin yapılması gerekiyor. Yeni linux sistemlerinde disk bölümlerine UUID'ler ile erişiliyor. Mevcut disk bölümlerinin UUID'lerine erişmek için blkid komutunu kullanmak gerek.

$ sudo blkid
Bu komutun sonunda /dev/sda8 bölümüne ait UUID'yi kopyalayarak /etc/fstab dosyasına şu şekilde girdim:

UUID="....."        swap          swap        defaults     0  0

Bir sonraki açılışta free komutu ile takas bölümünün mount edildiğini doğruladım, konu kapandı.

24.09.2017

xfce masaüstü özelleştirmeleri

Fedora xfce spin kullandığım bir dizüstü bilgisayarda ses açma / kapama ve medya tuşlarının (durdur, ileri, geri gibi) çalışmadığını farkettim. Bu duruma şu şekilde bir çözüm buldum:

Klavye ayarlarına girerek kısayollar sekmesine geçtim. Önce bir terminal penceresinde şu komutların ses açma / kapama görevi görüp görmediğini denedim:

amixer set Master 10000+
amixer set Master 10000-
Bu komutların işe yaradığını görerek klavye kısayollarına yeni tuşuna basarak bu komutları birer birer ekledim. Bittikten sonra da klavyedeki ilgili düğmeye basarak atamayı tamamladım.

Ses kapatma (mute) işlevi için de

amixer set Master toggle

komutunu kullandım. Profilimin altına .Xmodmap diye bir dosya oluşturmak ve içine

keycode 174 = XF86AudioLowerVolume
keycode 176 = XF86AudioRaiseVolume
keycode 162 = XF86AudioPlay
keycode 164 = XF86AudioStop
keycode 144 = XF86AudioPrev
keycode 153 = XF86AudioNext

ekleyerek xmodmap .Xmodmap komutunu çalıştırmak işe yaramadı maalesef.

Medya tuşları için kısayollar pragha uygulamasına atanmıştı. Kullanmadığım bir uygulamaydı,

sudo dnf remove pragha

komuduyla bu uygulamadan kurtuldum. Ama klavye kısayollarında bu kaldı. Bu kısayolları Spotify ile kullanabilmek istiyordum. Bu girişleri çift tıklayarak durdurma için
dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause
komudunu kullandım. Karşısındaki XF86AudioPlay durum için uygundu; dokunmadım. Sonraki şarkıya geçiş için
dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next
komudunu kullandım. Karşısındaki XF86AudioNext durum için uygundu; değiştirmedim. Önceki şarı geçişi için
dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous
komudunu kullandım. Bunun karşısındaki XF86AudioPrev de uygundu, değiştirmedim.

Şu anda Spotify'ı sorunsuz olarak kullanabiliyorum.

Ayrıca şifre ekranındaki duvar kağıdını değiştirebileceğim bir yer de bulamıyordum. Bunun çözümünü de şöyle buldum:

/etc/lightdm/ klasörünün altındaki lightdm-gtk-greeter.conf dosyasını root ile (ya da sudo) açıp [greeter] başlığının altındaki background öğesinin değerini değiştirdim. Yalnız profilimin altındaki bir yolu göstermem çözüm olmadı. Bunun için istediğim dosyayı da /usr/share/background/ klasörüne kopyaladım.