cmp Komutu ile İkili Dosya Karşılaştırma Rehberi
İki dosyanın gerçekten aynı olup olmadığını anlamanız gerektiğinde, diff komutuna uzanmak ilk içgüdü olabilir. Ama diff metin dosyaları için tasarlanmıştır ve ikili dosyalarla çalışırken size pek yardımcı olmaz. İşte tam bu noktada cmp devreye giriyor. Sessiz, hızlı ve ikili dosya karşılaştırma konusunda son derece yetenekli bu araç, sistem yöneticilerinin araç kutusunda hak ettiği yeri çoğu zaman bulamıyor. Bu yazıda cmp komutunu her yönüyle ele alacağız.
cmp Nedir ve Ne Zaman Kullanılır?
cmp (compare), iki dosyayı byte byte karşılaştıran bir Unix/Linux aracıdır. Metin dosyalarında da çalışır ama asıl gücünü ikili dosyalarda gösterir: firmware imajları, veritabanı dosyaları, arşivler, çalıştırılabilir dosyalar ve disk imajları gibi durumlarda diff yetersiz kalırken cmp size tam olarak nerede farklılık olduğunu söyler.
Temel mantığı şudur: İki dosyayı karşılaştırır, farklılık bulduğunda hangi byte pozisyonunda ve hangi satırda olduğunu raporlar. Dosyalar aynıysa hiçbir şey söylemez (sessiz kalır) ve sıfır çıkış kodu döndürür. Bu davranış özellikle shell scriptlerinde son derece kullanışlıdır.
Ne zaman cmp tercih etmeliyiz?
- Firmware veya BIOS güncelleme dosyalarını doğrularken
- Yedekleme dosyalarının orijinalle aynı olup olmadığını kontrol ederken
- İki disk imajını karşılaştırırken
- Bir binary’nin beklenmedik şekilde değişip değişmediğini denetlerken
- Şüpheli bir sistemde kritik dosyaların bütünlüğünü kontrol ederken
- CI/CD pipeline’larında build artifact’larını doğrularken
Temel Kullanım
En basit haliyle cmp iki argüman alır:
cmp dosya1 dosya2
Eğer dosyalar aynıysa komut hiçbir çıktı vermez ve exit code 0 döner. Farklılarsa ilk farklılığın yerini gösterir:
$ cmp /bin/ls /bin/cp
/bin/ls /bin/cp differ: byte 25, line 1
Bu çıktı bize şunu söylüyor: İki dosya 25. byte’ta farklılaşıyor ve bu farklılık 1. satırda. İkili dosyalar için “satır” kavramı pek anlamlı olmasa da cmp newline karakterlerini sayarak satır bilgisini verir.
Exit code’ları şu şekilde yorumlanır:
- 0: Dosyalar aynı
- 1: Dosyalar farklı
- 2: Hata oluştu (dosya bulunamadı, erişim izni yok vb.)
Parametreler ve Bayraklar
cmp komutunun az ama etkili parametreleri vardır:
-l (–verbose): Tüm farklılıkları listeler, sadece ilkini değil. Her farklı byte için decimal byte pozisyonu ve her iki dosyadaki octal değerleri gösterir.
-s (–silent veya –quiet): Sessiz mod. Hiçbir çıktı vermez, sadece exit code döner. Script’lerde kullanmak için idealdir.
-i N (–ignore-initial=N): Her iki dosyanın başından N byte’ı atlar. Dosyaların başında header bilgisi gibi farklı veriler varsa kullanışlıdır.
-i N:M: İlk dosyanın başından N, ikinci dosyanın başından M byte’ı atlar.
-n N (–bytes=N): Sadece ilk N byte’ı karşılaştırır.
-b (–print-bytes): -l ile birlikte kullanılır. Byte değerlerini ASCII olarak da gösterir.
Kod Örnekleri ile Pratik Kullanım
Örnek 1: Basit Dosya Karşılaştırması
# İki konfigürasyon dosyasının binary olarak aynı olup olmadığını kontrol et
cmp /etc/nginx/nginx.conf /backup/nginx.conf.bak
# Eğer farklıysa çıktı şöyle görünür:
# /etc/nginx/nginx.conf /backup/nginx.conf.bak differ: byte 1024, line 47
Örnek 2: Script İçinde Sessiz Karşılaştırma
Gerçek dünyada cmp en çok -s bayrağıyla shell script’leri içinde kullanılır:
#!/bin/bash
ORIGINAL="/opt/app/binary"
BACKUP="/backup/binary.bak"
if cmp -s "$ORIGINAL" "$BACKUP"; then
echo "Dosyalar identik, yedek güncel."
else
echo "UYARI: Dosyalar farklı! Yedek güncellenmesi gerekebilir."
exit 1
fi
Bu pattern özellikle kritik binary’lerin değişip değişmediğini izleyen monitoring script’lerinde çok işe yarar.
Örnek 3: Tüm Farklılıkları Listeleme
# -l bayrağıyla tüm farklı byte'ları gör
cmp -l dosya1.bin dosya2.bin
# Örnek çıktı:
# 25 60 63
# 26 61 64
# 100 377 0
# Sütunlar: byte_no dosya1_octal dosya2_octal
Çıktıyı daha okunabilir hale getirmek için wc -l ile birleştirebilirsiniz:
# Kaç byte farklı olduğunu bul
cmp -l dosya1.bin dosya2.bin | wc -l
Örnek 4: Belirli Byte Aralığını Karşılaştırma
Bir firmware dosyasının sadece belirli bir bölümünü karşılaştırmak istediğinizde:
# İlk 512 byte'ı atla (örneğin MBR header), sonrasını karşılaştır
cmp -i 512 disk_image_v1.img disk_image_v2.img
# Sadece ilk 1024 byte'ı karşılaştır
cmp -n 1024 firmware_old.bin firmware_new.bin
# İlk dosyanın 100. byte'ından, ikinci dosyanın 200. byte'ından başla
cmp -i 100:200 dosya1.bin dosya2.bin
Örnek 5: Disk İmajı Doğrulama
Gerçek bir senaryo: Bir ISO dosyasını yazdıktan sonra USB’deki içeriğin doğru olup olmadığını kontrol etmek:
# USB'ye yazdığınız ISO ile orijinali karşılaştır
# ISO boyutu kadar byte karşılaştır
ISO_SIZE=$(stat -c%s ubuntu-22.04.iso)
cmp -n "$ISO_SIZE" ubuntu-22.04.iso /dev/sdb
if [ $? -eq 0 ]; then
echo "USB doğrulama başarılı, imaj bütünlüğü korunmuş."
else
echo "HATA: USB içeriği ISO ile uyuşmuyor!"
fi
Örnek 6: Çoklu Dosya Karşılaştırması
Birden fazla dosyayı bir referansla karşılaştırmak için döngü kullanabilirsiniz:
#!/bin/bash
REFERENCE="/opt/trusted/app_binary"
CHECK_DIR="/opt/deployed/"
echo "Bütünlük kontrolü başlatılıyor..."
FAILED=0
for binary in "$CHECK_DIR"*; do
filename=$(basename "$binary")
ref_file="/opt/trusted/$filename"
if [ -f "$ref_file" ]; then
if ! cmp -s "$binary" "$ref_file"; then
echo "[UYARI] Değişiklik tespit edildi: $filename"
FAILED=$((FAILED + 1))
else
echo "[OK] $filename"
fi
fi
done
if [ $FAILED -gt 0 ]; then
echo "Toplam $FAILED dosyada değişiklik var!"
exit 1
else
echo "Tüm dosyalar bütünlük kontrolünden geçti."
fi
Örnek 7: cmp ile md5sum Kombinasyonu
Büyük dosyalar için önce hash kontrolü, sonra detaylı cmp yaklaşımı performans açısından daha verimli olabilir:
#!/bin/bash
dosya1="$1"
dosya2="$2"
# Önce hızlı hash kontrolü
hash1=$(md5sum "$dosya1" | awk '{print $1}')
hash2=$(md5sum "$dosya2" | awk '{print $1}')
if [ "$hash1" = "$hash2" ]; then
echo "Hash'ler eşleşiyor, dosyalar aynı."
else
echo "Hash'ler farklı, detaylı karşılaştırma yapılıyor..."
# İlk farklılığın nerede olduğunu bul
cmp "$dosya1" "$dosya2"
# Kaç byte farklı?
diff_count=$(cmp -l "$dosya1" "$dosya2" | wc -l)
echo "Toplam $diff_count byte farklı."
fi
Gerçek Dünya Senaryoları
Senaryo 1: Sunucu Güvenlik Denetimi
Bir sabah erken saatte uyarı aldınız: Üretim sunucusunda kritik bir binary değişmiş olabilir. Classik bir file integrity monitoring durumu. cmp burada ilk başvuracağınız araçlardan biri olabilir:
# Güvenilir yedekten kritik sistem binary'lerini karşılaştır
CRITICAL_BINS=("/bin/bash" "/bin/su" "/usr/bin/sudo" "/sbin/sshd")
for bin in "${CRITICAL_BINS[@]}"; do
backup_path="/secure_backup${bin}"
if [ -f "$backup_path" ]; then
if ! cmp -s "$bin" "$backup_path"; then
echo "KRİTİK UYARI: $bin değiştirilmiş!"
# Byte seviyesinde fark nerede?
cmp "$bin" "$backup_path"
fi
fi
done
Bu tür kontroller Tripwire veya AIDE gibi araçların yaptığını basit düzeyde taklit ediyor. Küçük ortamlar için hafif ve etkili bir çözüm.
Senaryo 2: Yedekleme Doğrulama
Yedekleme işleri her gece çalışıyor ama yedekler gerçekten sağlam mı? rsync sonrası spot kontrol:
#!/bin/bash
# Yedek doğrulama scripti
SOURCE_DIR="/var/lib/postgresql/data"
BACKUP_DIR="/backup/postgresql/data"
# Kritik dosyaları kontrol et
CRITICAL_FILES=("pg_hba.conf" "postgresql.conf" "PG_VERSION")
for f in "${CRITICAL_FILES[@]}"; do
if cmp -s "${SOURCE_DIR}/${f}" "${BACKUP_DIR}/${f}"; then
echo "[OK] $f yedekle uyuşuyor."
else
echo "[FAIL] $f yedeği güncel değil veya bozuk!"
fi
done
Senaryo 3: Firmware Güncelleme Doğrulama
Gömülü sistemler veya ağ ekipmanları üzerinde çalışıyorsanız firmware dosyalarının bütünlüğü kritiktir:
# İndirilen firmware ile checksum doğrulaması yeterli değilse
# İki firmware versiyonunu karşılaştır
FIRMWARE_OLD="router_fw_v2.1.bin"
FIRMWARE_NEW="router_fw_v2.2.bin"
echo "Firmware boyutları:"
ls -la "$FIRMWARE_OLD" "$FIRMWARE_NEW"
echo ""
echo "İlk farklılık noktası:"
cmp "$FIRMWARE_OLD" "$FIRMWARE_NEW"
echo ""
echo "Toplam farklı byte sayısı:"
cmp -l "$FIRMWARE_OLD" "$FIRMWARE_NEW" | wc -l
Bu bilgi özellikle “bu firmware update ne kadar büyük değişiklik içeriyor?” sorusunu cevaplamak için kullanışlıdır.
Senaryo 4: CI/CD Pipeline’da Build Artifact Kontrolü
Deployment öncesi aynı commit’ten üretilen iki build artifact’ın birebir aynı olması gerektiği durumlar (reproducible builds):
#!/bin/bash
# ci_artifact_check.sh
BUILD1="build/output/app_v${BUILD_NUMBER}.tar.gz"
BUILD2="build/output/app_v${BUILD_NUMBER}_verify.tar.gz"
echo "Build artifact doğrulama..."
if cmp -s "$BUILD1" "$BUILD2"; then
echo "Build reproducible. Deployment onaylandı."
exit 0
else
echo "HATA: Build artifact'ları eşleşmiyor!"
echo "Detay:"
cmp "$BUILD1" "$BUILD2"
exit 1
fi
cmp vs Diğer Araçlar
cmp tek seçenek değil elbette, ama her aracın kendi nişi var.
cmp vs diff: diff metin odaklıdır, satır bazlı çalışır ve human-readable fark çıktısı üretir. cmp byte bazlıdır ve ikili dosyalar için tasarlanmıştır. Metin dosyası karşılaştırıyorsanız diff, binary dosya karşılaştırıyorsanız cmp tercih edin.
cmp vs md5sum/sha256sum: Hash’ler sadece “aynı mı, farklı mı” sorusunu cevaplar. cmp buna ek olarak “nerede farklı” sorusunu da cevaplar. Hızlı kontrol için hash, detaylı analiz için cmp kullanın.
cmp vs xxd + diff kombinasyonu: İki binary’nin hex dump’ını alıp diff’lemek cmp -l‘nin yaptığını farklı formatta yapar. Octal yerine hex görmek istiyorsanız bu yaklaşım tercih edilebilir ama cmp çok daha hızlıdır.
cmp vs strings: strings binary’den okunabilir metin dizilerini çıkarır. cmp ise ham byte karşılaştırması yapar. Farklı amaçlar için farklı araçlar.
Performans ve Büyük Dosyalar
cmp büyük dosyalarla çalışırken oldukça verimlidir çünkü ilk farklılığı bulduğu anda durur (varsayılan modda). Ancak -l bayrağıyla tüm farklılıkları tarıyorsanız ve dosya çok büyükse bu işlem zaman alabilir.
Büyük dosyalar için pratik yaklaşım:
# Önce boyutları karşılaştır, aynıysa devam et
size1=$(stat -c%s dosya1.img)
size2=$(stat -c%s dosya2.img)
if [ "$size1" -ne "$size2" ]; then
echo "Boyutlar farklı: $size1 vs $size2 byte"
exit 1
fi
# Boyutlar aynıysa cmp ile karşılaştır
# Büyük dosyalar için timeout ekle
timeout 300 cmp -s dosya1.img dosya2.img
exit_code=$?
case $exit_code in
0) echo "Dosyalar aynı." ;;
1) echo "Dosyalar farklı." ;;
124) echo "Zaman aşımı!" ;;
*) echo "Hata oluştu." ;;
esac
Çok büyük disk imajlarıyla çalışırken (100GB+ gibi) önce md5sum veya sha256sum ile hash kontrolü yapmak daha pratik olabilir. cmp en çok birkaç GB’a kadar olan dosyalarda günlük kullanımda tercih edilir.
İpuçları ve Dikkat Edilmesi Gerekenler
Dosya izinleri: cmp dosya içeriğini karşılaştırır, dosya izinlerini değil. İki dosyanın içeriği aynı olsa bile izinleri farklı olabilir. Bütünlük kontrolü yapıyorsanız izinleri de ayrıca kontrol edin.
Sembolik linkler: cmp sembolik linklerin hedef dosyasını karşılaştırır, linkin kendisini değil. Eğer iki link aynı hedefe işaret ediyorsa cmp onları aynı kabul eder.
Boş dosyalar: İki boş dosya her zaman aynıdır cmp açısından. Beklediğiniz bu değilse dosya boyutunu da kontrol edin.
Standard input kullanımı: - ile stdin’den okuyabilirsiniz:
# Bir komutun çıktısını dosyayla karşılaştır
dd if=/dev/urandom bs=1024 count=1 2>/dev/null | cmp - referans.bin
Exit code kontrolü: Her zaman exit code’u kontrol edin. cmp -s kullanırken bile hata durumunu (exit 2) ayrıca ele almak iyi bir pratiktir.
Sonuç
cmp komutu sade görünümünün arkasında son derece güvenilir bir araçtır. Özellikle güvenlik denetimleri, yedekleme doğrulaması ve ikili dosya bütünlüğü kontrolleri söz konusu olduğunda araç kutunuzda mutlaka bulunmalı. -s bayrağıyla script’lerde koşullu mantık kurmanızı sağlar, -l bayrağıyla byte seviyesinde detaylı analiz yapmanıza imkan tanır.
Her günlük işte kullanacağınız bir komut değil, ama ihtiyaç duyduğunuzda tam olarak ne aradığınızı yapan, beklediğiniz gibi davranan bir araç. Özellikle gece yarısı bir üretim sunucusunda “bu binary değişti mi?” sorusunu hızla cevaplamak istediğinizde, cmp -s ile yazdığınız tek satır sizi çok uzun debug süreçlerinden kurtarabilir.
