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.
