Linux dünyasında metin işlemenin olmazsa olmazlarından biri olan awk, özellikle log analizi, rapor oluşturma ve veri dönüştürme konularında sistem yöneticilerinin en güçlü silahlarından biridir. Ancak birçok sysadmin awk‘ı ya hiç kullanmaz ya da sadece yüzeysel komutlarla geçiştirir. Bu yazıda awk‘ın belki de en temel konseptine, yani alanlara (fields) odaklanacağız ve gerçek dünya senaryolarıyla bu kavramı derinlemesine ele alacağız.
awk Nedir ve Neden Önemlidir?
awk aslında bir programlama dilidir. Alfred Aho, Peter Weinberger ve Brian Kernighan tarafından 1977 yılında geliştirilmiştir ve isimleri bu üç kişinin soyadının baş harflerinden oluşur. Satır satır metin okuyarak her satırda belirttiğiniz işlemleri uygular.
awk‘ın temel çalışma mantığı şu şekildedir: Her satırı okur, bu satırı belirli bir ayraç karakterine göre alanlara böler ve siz bu alanlara erişerek istediğiniz işlemleri yaparsınız. Bu kadar basit ama bu kadar güçlü.
Bir Linux/Windows ortamında awk‘ı öğrenmek neden bu kadar kritik? Çünkü her gün karşılaştığınız log dosyaları, konfigürasyon çıktıları, network trafiği analizleri, kullanıcı raporları hepsi düzenli yapılandırılmış metin verileridir. awk bu verileri cerrahi bir hassasiyetle kesip biçmenizi sağlar.
Alanlara Giriş: $1, $2, $NF
awk bir satırı okuduğunda, bu satırı boşluk veya tab karakterlerine göre parçalara böler. Bu parçaların her birine alan (field) denir.
- $0: Tüm satırı temsil eder
- $1: Birinci alanı temsil eder
- $2: İkinci alanı temsil eder
- $NF: Son alanı temsil eder (NF = Number of Fields)
- $(NF-1): Sondan ikinci alanı temsil eder
Basit bir örnekle başlayalım. Diyelim ki /etc/passwd dosyasından kullanıcı adlarını almak istiyoruz:
awk -F: '{print $1}' /etc/passwd
Burada -F: parametresi alan ayracının : karakteri olduğunu belirtir. {print $1} ise her satırın ilk alanını, yani kullanıcı adını ekrana basar.
Şimdi daha karmaşık bir senaryo. Sistemdeki kullanıcıların kabuk (shell) bilgilerini de görmek istiyoruz:
awk -F: '{print $1, $7}' /etc/passwd
Bu komut kullanıcı adını ve kullandığı shell’i yan yana basar. Çıktı şu şekilde görünür:
root /bin/bash
daemon /usr/sbin/nologin
www-data /usr/sbin/nologin
Alan Ayracı (Field Separator) Kullanımı
awk‘ta alan ayracını iki şekilde belirtebilirsiniz:
-F parametresi ile:
awk -F',' '{print $2}' veriler.csv
BEGIN bloğu içinde FS değişkeni ile:
awk 'BEGIN{FS=","} {print $2}' veriler.csv
Her iki yöntem de aynı sonucu verir. Ancak BEGIN bloğu kullanmak, birden fazla ayraç veya karmaşık regex ayraçları için daha esnektir.
Peki ya birden fazla karakter ayraç olarak kullanmak istiyorsanız? Bunu regex ile halledebilirsiniz:
# Hem virgül hem noktalı virgül ayraç olarak kullanalım
awk -F'[,;]' '{print $1, $3}' karisik_veri.txt
Bu yaklaşım özellikle temizlenmemiş veri dosyalarıyla çalışırken hayat kurtarır.
Gerçek Dünya Senaryosu 1: Apache Log Analizi
Bir web sunucusunu yönetiyorsunuz ve Apache access log’unu analiz etmeniz gerekiyor. Log formatı şu şekilde:
192.168.1.100 - frank [10/Oct/2023:13:55:36 -0700] "GET /index.html HTTP/1.1" 200 2326
En fazla istek yapan IP adreslerini bulmak için:
awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn | head -20
Bu komut zinciri şunları yapar: awk ile IP adreslerini çeker, sort ile sıralar, uniq -c ile tekrar sayısını hesaplar, tekrar sort -rn ile büyükten küçüğe sıralar ve head -20 ile ilk 20 sonucu gösterir.
Sadece 404 hatalarını veren istekleri bulmak istiyorsanız:
awk '$9 == 404 {print $1, $7}' /var/log/apache2/access.log
Burada $9 HTTP durum kodunu, $7 ise istenen URL’yi temsil eder. Bu koşullu filtreleme awk‘ın en güçlü özelliklerinden biridir.
OFS: Çıktı Alan Ayracı
Giriş ayracını öğrendik, peki ya çıktı ayracı? awk varsayılan olarak alanları boşlukla ayırarak basar. Bunu değiştirmek için OFS (Output Field Separator) değişkenini kullanırız.
# /etc/passwd'den CSV formatında rapor oluştur
awk -F: 'BEGIN{OFS=","} {print $1,$3,$4,$7}' /etc/passwd
Bu komutun çıktısı şu şekilde olacak:
root,0,0,/bin/bash
daemon,1,1,/usr/sbin/nologin
Bu özellik, farklı formatlardaki verileri dönüştürmek için inanılmaz derecede kullanışlıdır. Örneğin bir sistem raporunu spreadsheet’e aktarmak için CSV’ye dönüştürebilirsiniz.
Alan Sayısını Kullanmak: NF Değişkeni
NF değişkeni her satırdaki alan sayısını tutar. Bu değişkeni hem kontrol hem de son alana erişmek için kullanabilirsiniz.
# Boş olmayan satırları, yani en az bir alanı olanları göster
awk 'NF > 0' dosya.txt
# Her satırdaki alan sayısını göster
awk '{print NF, $0}' dosya.txt
# Son iki alanı göster
awk '{print $(NF-1), $NF}' dosya.txt
Gerçek bir senaryo düşünelim. Bir konfigürasyon dosyasını parse ediyorsunuz ve bazı satırlar yorum satırı ya da boş:
# # ile başlayan ve boş satırları atlayarak sadece geçerli config satırlarını çek
awk 'NF > 0 && $1 !~ /^#/ {print $1, $2}' /etc/ssh/sshd_config
Gerçek Dünya Senaryosu 2: Disk Kullanım Raporu
Sisteminizdeki disk kullanımını izliyorsunuz ve df -h çıktısını işlemeniz gerekiyor:
df -h | awk 'NR > 1 && $5+0 > 80 {print "UYARI: " $6 " - Kullanim: " $5}'
Bu komut NR > 1 ile başlık satırını atlar, $5+0 > 80 ile kullanım yüzdesini kontrol eder (string’i sayıya çevirmek için +0 kullandık) ve 80% üzerindeki bölümleri uyarı mesajıyla gösterir.
Daha kapsamlı bir disk raporu için:
df -h | awk 'NR==1 {print "=== DISK KULLANIM RAPORU ==="}
NR > 1 {
gsub(/%/, "", $5)
if ($5+0 >= 90) durum="KRITIK"
else if ($5+0 >= 80) durum="UYARI"
else durum="NORMAL"
print $6 ": " $5"% [" durum "]"
}'
Alan Değerlerini Değiştirmek
awk sadece alan okumakla kalmaz, bu alanları değiştirmenize de izin verir:
# /etc/passwd'de shell'i bash olmayanları bul ve çıktıyı düzenle
awk -F: 'BEGIN{OFS=":"} $7 != "/bin/bash" {$7="/bin/sh"; print}' /etc/passwd
Bu örnekte $7 alanını değiştirdikten sonra print ile tüm satırı (yeni değeriyle birlikte) basıyoruz. OFS=":" sayesinde çıktı da : ile ayrılmış olacak.
Başka bir senaryo, log dosyasındaki IP adreslerini maskelemek:
awk '{
split($1, ip, ".")
ip[4] = "xxx"
$1 = ip[1]"."ip[2]"."ip[3]"."ip[4]
print
}' /var/log/apache2/access.log
Gerçek Dünya Senaryosu 3: Ağ Bağlantı Analizi
Sunucunuzdaki aktif bağlantıları analiz etmek istiyorsunuz. ss -tn veya netstat -tn çıktısını işleyelim:
ss -tn | awk 'NR > 1 {
split($5, addr, ":")
remote_ip = addr[1]
count[remote_ip]++
}
END {
print "=== BAGLANTI SAYILARI ==="
for (ip in count) {
if (count[ip] > 5)
print ip ": " count[ip] " baglanti"
}
}'
Bu script her uzak IP’den kaç bağlantı geldiğini sayar ve 5’ten fazla bağlantısı olanları listeler. Potansiyel DDoS veya kötü niyetli tarama aktivitelerini tespit etmek için kullanışlıdır.
BEGIN ve END Blokları ile Alan İşleme
BEGIN bloğu dosya okunmadan önce, END bloğu ise tüm satırlar işlendikten sonra çalışır. Bu blokları alan işlemeyle birleştirince güçlü raporlar oluşturabilirsiniz.
# Bir servis logundaki toplam trafik hesabı
awk 'BEGIN {
print "Analiz basliyor..."
toplam = 0
}
{
toplam += $10 # byte cinsinden transfer edilen veri
satir++
}
END {
print "Toplam satir: " satir
print "Toplam transfer: " toplam/1024/1024 " MB"
print "Ortalama transfer: " toplam/satir " byte"
}' /var/log/apache2/access.log
Çok Karakterli Alan Ayracı
Bazen alan ayracı tek bir karakter değil, birden fazla karakterden oluşan bir string olabilir. Örneğin bazı log formatlarında || veya :: gibi ayraçlar kullanılır:
# :: ile ayrılmış özel log formatı
awk -F'::' '{print $1, $3}' ozel_log.txt
# Tab karakteri ile ayrılmış dosya
awk -F't' '{print $2, $4}' sekme_ayracli.tsv
# Birden fazla boşluk karakterini tek ayraç olarak kullan
awk -F' +' '{print $1, $3}' bosluklu_dosya.txt
Koşullu Alan İşleme
awk‘ın gerçek gücü koşullu mantıkla birleştiğinde ortaya çıkar:
# Sadece belirli bir alanda pattern eşleşen satırları işle
awk '$4 ~ /ERROR/ {print NR": "$0}' sistem.log
# Sayısal karşılaştırma
awk '$3 > 1000 && $3 < 5000 {print $1, $2, $3}' rapor.txt
# Birden fazla koşul
awk '$1 == "CRITICAL" || $1 == "ERROR" {
print strftime("%Y-%m-%d %H:%M:%S"), $0
}' uygulama.log
Gerçek Dünya Senaryosu 4: Kullanıcı Hesap Raporu
Sistem yöneticisi olarak periyodik kullanıcı raporları hazırlamak zorunda olabilirsiniz. /etc/passwd dosyasından anlamlı bir rapor çıkaralım:
awk -F: 'BEGIN {
OFS="t"
print "KULLANICItUIDtGIDtHOMEtSHELL"
print "-------t---t---t----t-----"
}
$3 >= 1000 && $3 != 65534 {
print $1, $3, $4, $6, $7
}
END {
print "nToplam normal kullanici sayisi: " NR-2
}' /etc/passwd
Bu script sistem kullanıcılarını (UID < 1000) atlayarak sadece gerçek kullanıcıları listeler ve başlık satırı ekler.
Alan İşlemede Yaygın Hatalar ve Çözümleri
Sayısal karşılaştırma hataları: awk string ve sayı karşılaştırmalarında bazen beklenmedik davranabilir.
# Yanlis - string karsilastirmasi yapar
awk '$3 > "100"' dosya.txt
# Dogru - sayisal karsilastirma
awk '$3+0 > 100' dosya.txt
# veya
awk 'int($3) > 100' dosya.txt
Boşluk içeren alanlara erişim: Eğer bir alanda boşluk varsa ve bu alanı tırnak içinde çekmek istiyorsanız, önce ayracı doğru belirlemeniz gerekir.
# Tırnak içindeki değerleri de ayrac olarak kullanmak
awk -F'"' '{print $2}' tirnak_icinde.txt
Satır sonu karakterleri: Windows’tan gelen dosyalarda rn satır sonu olabilir ve bu alanları bozabilir.
# Satir sonu karakterlerini temizle
awk '{gsub(/r/, ""); print $NF}' windows_dosyasi.txt
Pratik İpuçları ve Kısayollar
awk scriptlerini daha okunaklı yazmak için birkaç öneri:
- Uzun scriptleri
-fparametresiyle dosyadan okuyun:awk -f script.awk veri.txt - Değişken tanımlamayı
-vparametresiyle yapın:awk -v esik=80 '$5+0 > esik {print}' dosya.txt printyerineprintfkullanarak formatlanmış çıktı alın
# printf ile duzgun hizalanmis rapor
awk -F: '$3 >= 1000 {printf "%-15s %-5s %-30sn", $1, $3, $6}' /etc/passwd
Birden fazla dosyayı aynı anda işlerken hangi dosyanın işlendiğini FILENAME değişkeniyle takip edebilirsiniz:
awk 'FNR == 1 {print "=== " FILENAME " ==="} {print $1}' *.log
Burada FNR her dosya için sıfırlanan satır numarasıdır, NR ise tüm dosyalar boyunca artan toplam satır numarasıdır.
Sonuç
awk‘ın alan sistemi, metin işlemenin temel taşını oluşturur. $1‘den $NF‘e kadar olan alan notasyonunu, FS ve OFS değişkenlerini, koşullu alan işlemeyi ve gerçek senaryolardaki uygulamalarını gördük.
Bir sysadmin olarak awk‘ı iyi bilmek, günlük iş yükünüzü ciddi ölçüde azaltır. Log analizi, rapor oluşturma, konfigürasyon dosyası parse etme, ağ trafiği analizi gibi onlarca görevi birkaç satır awk kodu ile halledebilirsiniz.
Pratik yapmak için önerim şu: Hemen şu an çalıştığınız sunucuya gidin, df -h, ss -tn veya /var/log/syslog gibi bir çıktı alın ve bu yazıdaki teknikleri uygulayın. awk‘ı öğrenmenin en iyi yolu onu gerçek verilerle, gerçek problemleri çözerek kullanmaktır.
Bir sonraki yazıda awk‘ta döngüler, diziler ve daha gelişmiş programlama yapılarını ele alacağız. O zamana kadar terminal açık, awk hazır!