diff Komutu ile İki Dosya Arasındaki Farkları Bulma

Sistem yöneticiliğinde en sık karşılaştığımız durumlardan biri şu: “Bu dosya dün farklıydı, ne değişti?” sorusunu cevaplamak. İster bir konfigürasyon dosyasının gizlice değiştirilmesini fark etmeye çalışıyor ol, ister iki ortam arasındaki farkları bulmak isteyin, diff komutu bu işin olmazsa olmazıdır. Yıllardır her gün kullandığım bu araç, basit görünümünün arkasında inanılmaz derecede güçlü özellikler barındırıyor. Bu yazıda diff komutunu her yönüyle inceleyeceğiz.

diff Komutu Nedir ve Ne İşe Yarar?

diff (difference), iki dosya veya dizin arasındaki farklılıkları satır satır karşılaştırıp gösteren bir Unix/Linux komutudur. 1970’lerden bu yana Unix dünyasında var olan bu araç, bugün hala modern sistemlerde aktif olarak kullanılıyor. Git gibi versiyon kontrol sistemlerinin de temelinde diff algoritması yatıyor.

Temel kullanım amacı şunlardır:

  • Konfigürasyon değişikliklerini izlemek: Bir servis beklenmedik davranış sergilemeye başladığında konfigürasyon dosyasında ne değişti diye bakmak
  • Yazılım sürümleri arasındaki farkları görmek: Hangi satırlar eklendi, hangileri silindi
  • Dosya senkronizasyonu: İki makine arasında hangi dosyaların farklı olduğunu tespit etmek
  • Code review süreçleri: Değişiklikleri incelemek

Temel Kullanım

En basit haliyle diff şöyle çalışır:

diff dosya1.txt dosya2.txt

Hemen pratik bir örnek üzerinden gidelim. Elimizde iki nginx konfigürasyon dosyası olduğunu düşünelim:

# Mevcut konfigürasyonu yedekledik
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup

# Değişiklik yaptıktan sonra ne değişti bakalım
diff /etc/nginx/nginx.conf.backup /etc/nginx/nginx.conf

Bu komutun çıktısı ilk bakışta biraz kafa karıştırıcı gelebilir:

3c3
< worker_processes 2;
---
> worker_processes 4;
8a9
> gzip on;

Bu çıktıyı okumayı öğrenmek çok önemli. < işareti ilk dosyadaki (eski) satırı, > işareti ikinci dosyadaki (yeni) satırı gösteriyor. 3c3 ifadesi “3. satır değişti” anlamına geliyor, 8a9 ise “8. satırdan sonra 9. satır eklendi” demek.

Bu notasyon sistemi şöyle çalışır:

  • c (change): Satır değiştirilmiş
  • a (add): Satır eklenmiş
  • d (delete): Satır silinmiş

Önemli Parametreler

-u Parametresi: Unified Format

Gerçek hayatta en çok kullandığım format unified formattır. Git de bu formatı kullanır ve okunması çok daha kolaydır:

diff -u /etc/nginx/nginx.conf.backup /etc/nginx/nginx.conf

Çıktı şöyle görünür:

--- /etc/nginx/nginx.conf.backup    2024-01-15 10:30:00
+++ /etc/nginx/nginx.conf           2024-01-15 14:45:00
@@ -1,10 +1,11 @@
 user nginx;
 worker_processes 4;
-worker_connections 1024;
+worker_connections 2048;
 
+gzip on;
+gzip_types text/plain application/json;

Bu formatta + işareti eklenen satırları, - işareti silinen satırları gösteriyor. Değişmeyen satırlar boşlukla başlıyor. @@ -1,10 +1,11 @@ kısmı ise hangi satır aralığının gösterildiğini belirtiyor.

-c Parametresi: Context Format

diff -c dosya1.txt dosya2.txt

Bu format unified’a benzer ama biraz daha eski tarzdadır. Bazı eski sistemlerde veya araçlarda bunu görebilirsiniz.

-i Parametresi: Büyük/Küçük Harf Duyarsızlığı

diff -i dosya1.txt dosya2.txt

Büyük/küçük harf farklarını görmezden gelir. Konfigürasyon dosyalarında “ON” ile “on”un aynı anlama geldiği durumlarda işe yarar.

-b ve -B Parametreleri: Boşluk Farklarını Yoksayma

# Birden fazla boşluğu tek boşluk olarak değerlendir
diff -b dosya1.txt dosya2.txt

# Boş satır farklarını tamamen yoksay
diff -B dosya1.txt dosya2.txt

# İkisini birden kullan
diff -bB dosya1.txt dosya2.txt

Özellikle Python veya YAML dosyalarında çalışırken bunu dikkatli kullanmak gerekiyor çünkü bu dillerde boşluklar anlam taşıyor.

-w Parametresi: Tüm Boşlukları Yoksay

diff -w dosya1.txt dosya2.txt

Tüm whitespace karakterlerini yoksayar. Sadece gerçek içerik farklarını görmek istediğinizde kullanışlı.

-r Parametresi: Dizinleri Karşılaştırma

diff -r /etc/nginx/sites-available/ /backup/nginx/sites-available/

Dizinleri özyinelemeli (recursive) olarak karşılaştırır. Hangi dosyaların farklı olduğunu gösterir.

-q Parametresi: Sadece Farklı Dosyaları Listele

diff -rq /etc/nginx/ /backup/nginx/

Çıktı olarak sadece “Files X and Y differ” veya “Only in X: dosya” şeklinde kısa bilgi verir. Detaylı farkları göstermez, sadece hangi dosyaların farklı olduğunu öğrenmek istediğimizde harika.

–color Parametresi: Renkli Çıktı

diff --color=always dosya1.txt dosya2.txt

Terminalde renkli çıktı almanızı sağlar. Eklemeler yeşil, silmeler kırmızı görünür. Daha yeni sistemlerde --color varsayılan olarak destekleniyor ama eski sistemlerde bulunmayabilir.

Gerçek Dünya Senaryoları

Senaryo 1: SSH Konfigürasyonu Sorun Giderme

Bir gün gece 02:00’da telefon çaldı. SSH erişimi aniden kesilmişti ve sistem yöneticisi panik içindeydi. İlk iş elimizdeki yedekle mevcut konfigürasyonu karşılaştırmaktı:

diff -u /root/backups/sshd_config.$(date +%Y%m%d) /etc/ssh/sshd_config

Eğer tarihli yedeğiniz yoksa şöyle de yapabilirsiniz:

# Paketin orijinal konfigürasyonuyla karşılaştır
diff -u /usr/share/doc/openssh-server/examples/sshd_config /etc/ssh/sshd_config

Fark hemen ortaya çıktı: Birisi PermitRootLogin yes satırını PermitRootLogin no olarak değiştirmişti. Şimdi bu iyi bir şey aslında, ama yetkili kişi haberdar edilmemişti. Sorun çözüldü, değişiklik kayıt altına alındı.

Senaryo 2: Deployment Öncesi Konfigürasyon Kontrolü

Production ortamına deployment yapmadan önce staging ile production konfigürasyonlarını karşılaştırmak altın bir kural olmalı:

#!/bin/bash
# pre-deploy-check.sh

STAGING_CONF="/etc/myapp/config.yml"
PROD_CONF="user@production-server:/etc/myapp/config.yml"

# Önce production konfigürasyonunu çek
scp user@production-server:/etc/myapp/config.yml /tmp/prod-config.yml

# Karşılaştır
echo "=== Staging ile Production Konfigürasyon Farkları ==="
diff -u /tmp/prod-config.yml $STAGING_CONF

if [ $? -eq 0 ]; then
    echo "Konfigürasyonlar aynı, deployment güvenli."
else
    echo "DİKKAT: Konfigürasyon farkları var! Kontrol edin."
    exit 1
fi

Bu script deployment pipeline’ınıza eklenebilir. diff komutu dosyalar aynıysa exit code 0, farklıysa exit code 1 döner. Bu özelliği script’lerde koşullu kontroller için kullanabilirsiniz.

Senaryo 3: Log Dosyası Analizi

Bir uygulama iki farklı sunucuda farklı davranıyordu. Log formatları farklı mıydı diye kontrol ettik:

# Son 100 satırı al ve karşılaştır
tail -100 /var/log/app/server1.log > /tmp/log1.txt
tail -100 /var/log/app/server2.log > /tmp/log2.txt

# Zaman damgalarını yoksayarak karşılaştır (sed ile zaman damgasını temizle)
sed 's/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}//g' /tmp/log1.txt > /tmp/log1_clean.txt
sed 's/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}//g' /tmp/log2.txt > /tmp/log2_clean.txt

diff /tmp/log1_clean.txt /tmp/log2_clean.txt

Senaryo 4: Patch Dosyası Oluşturma

diff komutunun en güçlü özelliklerinden biri patch dosyası oluşturabilmesidir. Bu özellik özellikle kaynak kod yönetiminde ve sunucular arası değişiklik aktarımında çok işe yarar:

# Değişikliği patch dosyası olarak kaydet
diff -u orijinal_config.conf guncel_config.conf > nginx_changes.patch

# Bu patch dosyasını başka bir sunucuda uygula
patch /etc/nginx/nginx.conf < nginx_changes.patch

Patch dosyasının içeriği şöyle görünür:

--- orijinal_config.conf    2024-01-10 09:00:00
+++ guncel_config.conf      2024-01-15 14:30:00
@@ -45,7 +45,8 @@
     keepalive_timeout  65;
-    client_max_body_size 10m;
+    client_max_body_size 50m;
+    client_body_timeout 60;

Bu yöntem özellikle birden fazla sunucuya aynı değişikliği uygulamanız gerektiğinde çok kullanışlıdır. Değişikliği bir kez yapıp patch olarak dağıtırsınız.

diff ile Birlikte Kullanılan Araçlar

vimdiff: Görsel Karşılaştırma

Terminal içinde görsel karşılaştırma yapmak istiyorsanız vimdiff harika bir seçenek:

vimdiff dosya1.txt dosya2.txt

Vim açılır ve iki dosyayı yan yana gösterir. Farklı satırlar vurgulanır. Vim kısayollarını biliyorsanız ]c ve [c ile farklar arasında gezebilirsiniz. do ile diğer dosyadaki değişikliği alabilir, dp ile kendi değişikliğinizi diğerine aktarabilirsiniz.

colordiff: Renkli diff

Sisteminizde colordiff kuruluysa her zaman kullanın:

# Ubuntu/Debian
apt install colordiff

# CentOS/RHEL
yum install colordiff

# Kullanımı birebir diff ile aynı
colordiff -u dosya1.txt dosya2.txt

# diff çıktısını renklendir
diff -u dosya1.txt dosya2.txt | colordiff

wdiff: Kelime Bazlı Karşılaştırma

Satır bazlı değil kelime bazlı karşılaştırma için:

wdiff dosya1.txt dosya2.txt

Özellikle uzun satırların olduğu konfigürasyon veya belge dosyalarında hangi kelimelerin değiştiğini görmek için idealdir.

diff Çıktısını İşleme

grep ile Filtreleme

Büyük dosyaları karşılaştırırken sadece belirli değişiklikleri görmek isteyebilirsiniz:

# Sadece eklenen satırları göster
diff dosya1.txt dosya2.txt | grep "^>"

# Sadece silinen satırları göster
diff dosya1.txt dosya2.txt | grep "^<"

# Sadece belirli bir kelimeyle ilgili değişiklikleri göster
diff -u dosya1.txt dosya2.txt | grep -A2 -B2 "worker_processes"

Kaç Satır Değişti?

# Değişen satır sayısını öğren
diff dosya1.txt dosya2.txt | grep -c "^[<>]"

# Unified formatta daha detaylı istatistik
diff -u dosya1.txt dosya2.txt | diffstat

diffstat aracı yüklüyse değişiklik istatistiklerini güzel bir özet halinde sunar.

Dizin Karşılaştırması: Pratik Örnekler

Sık karşılaşılan bir durum: İki sunucu arasındaki konfigürasyon dizinlerini karşılaştırmak.

# Recursive olarak tüm dizini karşılaştır, sadece farklı dosyaları listele
diff -rq /etc/apache2/ /backup/apache2/

# Belirli dosya tiplerini hariç tut
diff -rq --exclude="*.log" --exclude="*.pid" /etc/app/ /backup/app/

# Belirli desenleri dahil et
diff -rq --include="*.conf" /etc/ /backup/etc/

Daha kapsamlı bir örnek: İki server’ın /etc dizinini karşılaştırmak istiyoruz ama önce dosya listesini alıp sonra karşılaştırıyoruz:

#!/bin/bash
# compare-configs.sh

SERVER1="server1.example.com"
SERVER2="server2.example.com"
COMPARE_DIR="/etc/myapp"

# Her iki sunucudan dosya listesi al
ssh $SERVER1 "find $COMPARE_DIR -type f | sort" > /tmp/server1_files.txt
ssh $SERVER2 "find $COMPARE_DIR -type f | sort" > /tmp/server2_files.txt

echo "=== Dosya Listesi Farkları ==="
diff /tmp/server1_files.txt /tmp/server2_files.txt

echo ""
echo "=== Ortak Dosyalardaki İçerik Farkları ==="

# Ortak dosyaları karşılaştır
while IFS= read -r file; do
    scp -q $SERVER1:$file /tmp/s1_temp
    scp -q $SERVER2:$file /tmp/s2_temp
    
    if ! diff -q /tmp/s1_temp /tmp/s2_temp > /dev/null 2>&1; then
        echo "--- Farklı: $file ---"
        diff -u /tmp/s1_temp /tmp/s2_temp
    fi
done < /tmp/server1_files.txt

Binary Dosyaları Karşılaştırma

diff normalde metin dosyaları için tasarlanmıştır. Binary dosyalarda şu mesajı alırsınız:

Binary files file1.bin and file2.bin differ

Binary dosyaları karşılaştırmak için cmp komutunu kullanabilirsiniz:

# Binary karşılaştırma
cmp dosya1.bin dosya2.bin

# Hangi byte'larda farklılık var
cmp -l dosya1.bin dosya2.bin

# Sadece aynı/farklı bilgisi
cmp -s dosya1.bin dosya2.bin && echo "Aynı" || echo "Farklı"

Otomatik İzleme: Cron ile diff

Kritik konfigürasyon dosyalarının değişip değişmediğini otomatik olarak izleyen basit bir sistem kuralım:

#!/bin/bash
# config-monitor.sh - Her gün çalıştırılacak

WATCH_FILES="/etc/ssh/sshd_config /etc/nginx/nginx.conf /etc/hosts /etc/sudoers"
BACKUP_DIR="/var/backups/config-snapshots"
DATE=$(date +%Y%m%d)
ALERT_EMAIL="[email protected]"

mkdir -p $BACKUP_DIR

for file in $WATCH_FILES; do
    filename=$(echo $file | tr '/' '_')
    backup_file="$BACKUP_DIR/${filename}.yesterday"
    
    if [ -f "$backup_file" ]; then
        if ! diff -q "$backup_file" "$file" > /dev/null 2>&1; then
            echo "UYARI: $file dosyasında değişiklik tespit edildi!" | 
            mail -s "Konfigürasyon Değişikliği Uyarısı" $ALERT_EMAIL < 
            <(diff -u "$backup_file" "$file")
        fi
    fi
    
    # Bugünkü versiyonu yedekle
    cp "$file" "$backup_file"
done

Bu scripti crontab’a ekleyin:

# Her gün sabah 08:00'de çalıştır
0 8 * * * /usr/local/bin/config-monitor.sh

Çıkış Kodlarını Kullanmak

diff komutunun çıkış kodlarını bilmek script yazmada kritik önem taşır:

  • 0: Dosyalar aynı
  • 1: Dosyalar farklı
  • 2: Hata oluştu
diff dosya1.txt dosya2.txt
case $? in
    0) echo "Dosyalar identik" ;;
    1) echo "Dosyalar farklı" ;;
    2) echo "Hata oluştu" ;;
esac

Daha pratik bir kullanım:

# Deployment öncesi kontrol
if diff -q staging.conf production.conf > /dev/null 2>&1; then
    echo "Konfigürasyonlar eşleşiyor, deployment başlatılıyor..."
    ./deploy.sh
else
    echo "Konfigürasyon uyuşmazlığı! Deployment iptal edildi."
    diff -u production.conf staging.conf
    exit 1
fi

Performans İpuçları

Büyük dosyaları veya dizinleri karşılaştırırken dikkat etmeniz gereken birkaç nokta var:

# Büyük log dosyalarında önce sıralayıp karşılaştır (daha hızlı)
sort dosya1.log > /tmp/s1.sorted
sort dosya2.log > /tmp/s2.sorted
diff /tmp/s1.sorted /tmp/s2.sorted

# Sadece belirli satır sayısına kadar karşılaştır
head -1000 buyuk_dosya1.txt > /tmp/sample1.txt
head -1000 buyuk_dosya2.txt > /tmp/sample2.txt
diff /tmp/sample1.txt /tmp/sample2.txt

Sonuç

diff komutu, sysadmin araç kutusunun vazgeçilmez parçalarından biridir. Yıllar içinde onlarca kez kritik sorunları çözmeme yardımcı oldu: Gece yarısı bozulan konfigürasyonları tespit etmekten deployment süreçlerindeki anomalileri yakalamaya kadar geniş bir yelpazede kullandım.

Temel kullanımı basit olsa da -u, -r, -q gibi parametrelerle ve diğer araçlarla kombinasyonu son derece güçlü iş akışları oluşturmanızı sağlıyor. Özellikle patch dosyası oluşturma özelliği, birden fazla sunucuya kontrollü değişiklik dağıtmak için hala en güvenilir yöntemlerden biri.

Konfigürasyon dosyalarınız için düzenli snapshot’lar alın ve diff ile karşılaştırmayı bir alışkanlık haline getirin. “Bu dosya ne zaman değişti?” sorusunu sormak zorunda kalmadan önce izleme mekanizmalarınızı kurun. Zira bir şeylerin bozulması, genellikle bir şeylerin değiştirilmesinden sonra gelir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir