comm Komutu ile Sıralı Dosyaları Karşılaştırma ve Fark Bulma

Linux üzerinde iki sıralı dosyayı karşılaştırmak için comm komutu hızlı ve etkili bir çözüm sunar. Hangi satırların ortak, hangilerinin yalnızca bir dosyada bulunduğunu tek komutla görebilirsiniz. Bu yazıda comm komutunun tüm seçeneklerini ve gerçek dünya kullanım senaryolarını inceliyoruz.

comm Komutu ile Sıralı Dosyaları Karşılaştırma ve Fark Bulma

Sysadmin hayatında “bu dosyada ne değişti?”, “hangi paketler eksik?”, “bu iki liste arasındaki fark nedir?” gibi sorularla sık sık karşılaşırsınız. Çoğu zaman akla ilk gelen diff komutudur. Ama comm komutunu biliyorsanız, bazı senaryolarda çok daha temiz ve kullanışlı sonuçlar elde edebilirsiniz.

Bu yazıda comm komutunu A’dan Z’ye ele alacağız. Gerçek dünya örnekleriyle, ne zaman kullanmanız gerektiğini ve diff‘ten nasıl farklılaştığını göstereceğim.

comm Nedir ve Ne Zaman Kullanılır?

comm, iki sıralı metin dosyasını satır satır karşılaştıran bir Unix aracıdır. Çıktısını üç sütun halinde verir:

  • Sütun 1: Sadece birinci dosyada olanlar
  • Sütun 2: Sadece ikinci dosyada olanlar
  • Sütun 3: Her iki dosyada da olanlar (ortak satırlar)

diff komutundan temel farkı şudur: diff değişiklik bloklarını gösterir, ekleme/silme satırlarını işaretler. comm ise setler teorisi mantığıyla çalışır. “A kümesinde olup B’de olmayan”, “B’de olup A’da olmayan”, “her ikisinde de olan” şeklinde düşünün.

Önemli bir not: Dosyalar mutlaka sıralı olmalıdır. Sıralı değilse comm yanlış sonuç üretir. Bu yüzden genellikle sort komutuyla birlikte kullanılır.

Temel Kullanım

Sözdizimi son derece basit:

comm [SECENEK] dosya1 dosya2

Üç temel seçenek vardır:

  • -1 : Birinci sütunu (sadece dosya1’de olanlar) gizle
  • -2 : İkinci sütunu (sadece dosya2’de olanlar) gizle
  • -3 : Üçüncü sütunu (ortak olanlar) gizle

Bu seçenekleri birleştirerek istediğiniz sonucu elde edersiniz.

İlk Örnek: Basit Karşılaştırma

Diyelim ki iki dosyanız var:

# dosya1.txt
cat > dosya1.txt << EOF
apache2
curl
git
mysql-server
nginx
php
EOF

# dosya2.txt
cat > dosya2.txt << EOF
apache2
docker
git
nginx
nodejs
php
redis
EOF

Şimdi comm ile karşılaştıralım:

comm dosya1.txt dosya2.txt

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

               apache2
curl
        docker
               git
mysql-server
               nginx
        nodejs
               php
        redis

Sütun 1 (girintisiz): Sadece dosya1’de olan -> curl, mysql-server Sütun 2 (bir tab girintili): Sadece dosya2’de olan -> docker, nodejs, redis Sütun 3 (iki tab girintili): Her ikisinde de olan -> apache2, git, nginx, php

Pratik Seçenek Kombinasyonları

Sadece Ortak Olanları Göster

comm -12 dosya1.txt dosya2.txt

Çıktı:

apache2
git
nginx
php

-1 ile sütun 1’i, -2 ile sütun 2’yi gizledik. Geriye sadece ortak olanlar kaldı. Bu aslında iki kümenin kesişimi.

Sadece Dosya1’de Olanları Göster

comm -23 dosya1.txt dosya2.txt

Çıktı:

curl
mysql-server

Sütun 2 ve 3’ü gizledik, sadece birinci dosyaya özgü olanlar kaldı. Bu A – B farkı.

Sadece Dosya2’de Olanları Göster

comm -13 dosya1.txt dosya2.txt

Çıktı:

docker
nodejs
redis

Bu da B – A farkı.

Gerçek Dünya Senaryoları

Senaryo 1: Kurulu Paket Listelerini Karşılaştırma

Yeni bir sunucu kuruyorsunuz ve mevcut production sunucusundaki paketlerin aynısının yüklü olmasını istiyorsunuz. Önce paket listelerini çıkarın, sonra karşılaştırın.

# Production sunucusunda
dpkg --get-selections | grep -v deinstall | awk '{print $1}' | sort > /tmp/prod_packages.txt
scp sunucu1:/tmp/prod_packages.txt /tmp/prod_packages.txt

# Yeni sunucuda
dpkg --get-selections | grep -v deinstall | awk '{print $1}' | sort > /tmp/new_packages.txt

# Prod'da olup yeni sunucuda olmayan paketler
comm -23 /tmp/prod_packages.txt /tmp/new_packages.txt

# Yeni sunucuda olup prod'da olmayan paketler (dikkat edilmesi gerekenler)
comm -13 /tmp/prod_packages.txt /tmp/new_packages.txt

Bu yöntemle kurulum eksikliklerini anında bulabilirsiniz. Onlarca paketi tek tek kontrol etmek yerine birkaç saniyede farkı görürsünüz.

Senaryo 2: Backup Dosyalarının Kontrolü

Bir dizindeki dosyaların yedeğe gittiğini doğrulamak istiyorsunuz:

# Kaynak dizindeki dosyalar
find /var/www/html -type f | sed 's|/var/www/html/||' | sort > /tmp/kaynak_dosyalar.txt

# Backup dizinindeki dosyalar
find /backup/www -type f | sed 's|/backup/www/||' | sort > /tmp/backup_dosyalar.txt

# Yedeğe gitmemiş dosyalar
echo "=== YEDEGE GITMEYEN DOSYALAR ==="
comm -23 /tmp/kaynak_dosyalar.txt /tmp/backup_dosyalar.txt

# Yedekte olup kaynakta olmayan dosyalar (silinmiş ama yedekte hala var)
echo "=== KAYNAKTA SILINMIS AMA YEDEKTE MEVCUT ==="
comm -13 /tmp/kaynak_dosyalar.txt /tmp/backup_dosyalar.txt

Bu script’i cron’a ekleyip düzenli backup kontrolü yapabilirsiniz.

Senaryo 3: Kullanıcı Hesaplarını Karşılaştırma

İki sunucu arasındaki kullanıcı farklarını bulmak:

# Her iki sunucudan kullanıcı listesi çekin
cut -d: -f1 /etc/passwd | sort > /tmp/sunucu1_users.txt
# Diğer sunucudan SSH ile
ssh sunucu2 "cut -d: -f1 /etc/passwd | sort" > /tmp/sunucu2_users.txt

# Sunucu1'de olup sunucu2'de olmayan kullanıcılar
echo "Sunucu1'e ozgu kullanicilar:"
comm -23 /tmp/sunucu1_users.txt /tmp/sunucu2_users.txt

# Her iki sunucuda da olan kullanıcılar
echo "Ortak kullanicilar:"
comm -12 /tmp/sunucu1_users.txt /tmp/sunucu2_users.txt

Senaryo 4: Log Analizi ile Başarısız Girişimler

Access log’larından dün başarılı giriş yapan kullanıcılarla bugün başarılı giriş yapanları karşılaştırın:

# Dünkü başarılı girişler (basit örnek)
grep "Accepted password" /var/log/auth.log.1 | awk '{print $9}' | sort -u > /tmp/dunku_girisler.txt

# Bugünkü başarılı girişler
grep "Accepted password" /var/log/auth.log | awk '{print $9}' | sort -u > /tmp/bugunku_girisler.txt

# Dün giriş yapıp bugün yapmayan kullanıcılar
echo "=== DUN GIRIS YAPIP BUGUN YAPMAYAN ==="
comm -23 /tmp/dunku_girisler.txt /tmp/bugunku_girisler.txt

# Bugün ilk kez giriş yapan kullanıcılar (dikkat!)
echo "=== BUGUN ILK KEZ GIRIS YAPAN ==="
comm -13 /tmp/dunku_girisler.txt /tmp/bugunku_girisler.txt

Sıralama Konusu: Dikkat Edilmesi Gerekenler

comm kullanırken en sık yapılan hata, sıralanmamış dosyaları vermektir. Bunu aşmanın en kolay yolu process substitution kullanmaktır:

# Dosyaları önceden sıralamak yerine
comm -12 <(sort liste1.txt) <(sort liste2.txt)

Büyük/küçük harf duyarlılığı da önemli bir konudur. Locale ayarlarına göre sıralama farklılaşabilir. Güvenli olmak için:

# Locale bağımsız sıralama
comm -12 <(sort -f liste1.txt) <(sort -f liste2.txt)

# Veya locale'yi tamamen devre dışı bırakın
LC_ALL=C comm -12 <(LC_ALL=C sort liste1.txt) <(LC_ALL=C sort liste2.txt)

comm ile Gelişmiş Kullanım

Çıktıyı Daha Okunabilir Hale Getirmek

Varsayılan tab girintisi bazen kafa karıştırabilir. --output-delimiter seçeneği ile bunu değiştirebilirsiniz:

comm --output-delimiter='|' dosya1.txt dosya2.txt

Ya da çıktıyı etiketleyerek daha anlaşılır hale getirebilirsiniz:

echo "=== SADECE DOSYA1 ==="
comm -23 dosya1.txt dosya2.txt

echo ""
echo "=== SADECE DOSYA2 ==="
comm -13 dosya1.txt dosya2.txt

echo ""
echo "=== ORTAK ==="
comm -12 dosya1.txt dosya2.txt

Script İçinde Kullanım: Otomatik Senkronizasyon Kontrolü

#!/bin/bash
# sync_check.sh - İki dizin arasındaki dosya farkını raporla

KAYNAK="/var/app/config"
HEDEF="/backup/config"
RAPOR="/var/log/sync_rapor.log"

kaynak_liste=$(find "$KAYNAK" -type f | sed "s|$KAYNAK/||" | sort)
hedef_liste=$(find "$HEDEF" -type f | sed "s|$HEDEF/||" | sort)

eksik=$(comm -23 <(echo "$kaynak_liste") <(echo "$hedef_liste"))
fazla=$(comm -13 <(echo "$kaynak_liste") <(echo "$hedef_liste"))
eslesme=$(comm -12 <(echo "$kaynak_liste") <(echo "$hedef_liste"))

echo "=== Sync Raporu: $(date) ===" >> "$RAPOR"
echo "Eslesen dosya sayisi: $(echo "$eslesme" | wc -l)" >> "$RAPOR"

if [ -n "$eksik" ]; then
    echo "UYARI: Yedege gitmeyen dosyalar:" >> "$RAPOR"
    echo "$eksik" >> "$RAPOR"
fi

if [ -n "$fazla" ]; then
    echo "BILGI: Yedekte olup kaynakta olmayan dosyalar:" >> "$RAPOR"
    echo "$fazla" >> "$RAPOR"
fi

comm vs diff: Hangisini Kullanmalısınız?

Bu ikisi farklı işler için tasarlanmıştır:

comm kullanın:

  • Liste karşılaştırmalarında (paket listeleri, kullanıcı listeleri, dosya listeleri)
  • Küme operasyonları istediğinizde (kesişim, fark, birleşim)
  • Satır bazında basit evet/hayır sorularında
  • Script’lerde programatik kullanımda

diff kullanın:

  • Metin dosyalarındaki içerik değişikliklerini görmek istediğinizde
  • Satırın neresinin değiştiğini görmek istediğinizde
  • Patch oluşturmak istediğinizde
  • Sıralı olmayan dosyaları karşılaştırmanız gerektiğinde

Performans Notu

comm son derece hızlı bir araçtır. Milyonlarca satırlık dosyalarda bile diff‘e kıyasla çok daha performanslıdır çünkü sadece sıralı listeyi doğrusal olarak tarar. Büyük log dosyaları veya büyük paket listelerinde bu fark belirgin şekilde hissedilir.

Sonuç

comm komutu, sistem yöneticilerinin araç kutusunda olması gereken ama sıklıkla göz ardı edilen bir utility. Özellikle iki liste arasındaki farkı bulmak, ortak elemanları tespit etmek veya senkronizasyon kontrolü yapmak gibi işlemlerde diff‘e kıyasla çok daha temiz ve anlaşılır sonuçlar üretiyor.

Hatırlamanız gereken birkaç temel nokta:

  • Dosyaların sıralı olması zorunlu, sort komutunu ihmal etmeyin
  • -12, -13, -23 kombinasyonlarını ezberleyin
  • Process substitution (<(komut)) ile çok güçlü one-liner’lar yazabilirsiniz
  • Script’lerde backup kontrolü, paket senkronizasyonu, kullanıcı yönetimi gibi görevler için birebir

Bir sonraki sefer “bu iki liste arasındaki fark nedir?” diye sorduğunuzda, direkt diff‘e atlamadan önce comm‘u düşünün. Çoğu zaman ihtiyacınız olan tam da budur.

cmp Komutu ile İkili Dosya Karşılaştırma Rehberi

cmp komutu, Linux sistemlerde iki dosyayı byte düzeyinde karşılaştırmak için kullanılan güçlü bir araçtır. Sunucu ortamlarında yapılandırma dosyalarını ve ikili dosyaları doğrulamak için sıklıkla tercih edilir. Bu rehberde cmp komutunun tüm seçeneklerini ve gerçek dünya kullanım senaryolarını ele alıyoruz.

cmp Komutu: İkili Dosya Karşılaştırma Rehberi

Web sunucusu yönetiminde en sık karşılaştığım durumlardan biri şu: İki sunucu arasında bir dosyanın gerçekten aynı olup olmadığını doğrulamam gerekiyor. diff komutu metin dosyaları için harika çalışıyor ama binary dosyalarda, derlenmiş uygulamalarda veya konfigürasyon dosyalarının tam bit karşılaştırmasında işler biraz farklı. İşte tam bu noktada cmp komutu devreye giriyor.

Bu yazıda cmp komutunu web sunucusu yönetimi perspektifinden ele alacağız. Nginx binary’lerini karşılaştırmaktan SSL sertifikalarını doğrulamaya, deployment kontrolünden backup doğrulamaya kadar gerçek dünya senaryolarıyla konuyu işleyeceğiz.

cmp Nedir ve Neden Kullanmalısınız?

cmp (compare), iki dosyayı byte byte karşılaştıran bir Unix aracıdır. diff komutundan temel farkı şudur: diff metin odaklı çalışır ve satır bazlı karşılaştırma yapar, cmp ise her türlü dosyayı ham byte düzeyinde karşılaştırır.

Web sunucusu yönetiminde bu ayrım kritik öneme sahip:

  • Binary dosyalar: Nginx, Apache, PHP binary’leri
  • Sıkıştırılmış dosyalar: .tar.gz, .zip paketleri
  • SSL/TLS sertifikaları ve anahtar dosyaları
  • Statik web varlıkları: Minify edilmiş JS/CSS dosyaları
  • Veritabanı dump dosyaları
  • Docker image katmanları

diff bu dosyalara baktığında ya hata verir ya da anlamsız çıktı üretir. cmp ise sizi asla yanıltmaz.

Temel Kullanım

Basit Karşılaştırma

cmp dosya1 dosya2

Eğer dosyalar aynıysa hiçbir çıktı üretmez ve exit code 0 döner. Farklıysa ilk farklı byte’ın konumunu bildirir:

cmp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
# Çıktı: /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup differ: byte 1024, line 45

Bu basit çıktı bile çok değerli bilgi içeriyor: Hangi byte ve hangi satırda fark başlıyor.

Önemli Seçenekler

cmp komutunun temel bayraklarını bilmek işinizi çok kolaylaştırır:

  • -l (–verbose): Farklı olan tüm byte’ları listeler
  • -s (–quiet): Sessiz mod, sadece exit code döner
  • -n NUM: Sadece ilk NUM byte’ı karşılaştırır
  • -i NUM: Baştan NUM byte atlanarak karşılaştırılır
  • -b: Farklı byte’ları yazdırılabilir karakter olarak gösterir

Gerçek Dünya Senaryoları

Senaryo 1: Deployment Doğrulama

Production sunucusuna yeni bir Nginx binary deploy ettiniz. Peki bu binary gerçekten doğru versiyon mu? MD5 hash kontrolü yerine doğrudan binary karşılaştırması yapabilirsiniz:

#!/bin/bash
# deploy-check.sh - Deployment sonrasi binary dogrulama

STAGING_BINARY="/tmp/nginx-new"
PROD_BINARY="/usr/sbin/nginx"
REFERENCE_BINARY="/opt/binaries/nginx-1.24.0-reference"

echo "=== Nginx Binary Karsilastirma ==="

# Staging ile reference karsilastir
if cmp -s "$STAGING_BINARY" "$REFERENCE_BINARY"; then
    echo "[OK] Staging binary referans ile eslesıyor"
else
    echo "[HATA] Staging binary referans ile eslesmıyor!"
    # Farkli byte sayisini bul
    DIFF_COUNT=$(cmp -l "$STAGING_BINARY" "$REFERENCE_BINARY" 2>/dev/null | wc -l)
    echo "[BILGI] Toplam $DIFF_COUNT byte farki tespit edildi"
    exit 1
fi

# Production'a kopyalandiktan sonra tekrar dogrula
if cmp -s "$PROD_BINARY" "$REFERENCE_BINARY"; then
    echo "[OK] Production binary basariyla deploy edildi"
else
    echo "[KRITIK] Production binary tutarsiz! Rollback gerekiyor!"
    exit 2
fi

echo "Deployment dogrulama tamamlandi."

Bu script deployment pipeline’ınıza kolayca entegre edilebilir. Exit code kontrolü sayesinde CI/CD sistemleriniz hataları otomatik yakalayabilir.

Senaryo 2: SSL Sertifika ve Anahtar Eşleşme Kontrolü

Web sunucusu yönetiminde en sinir bozucu hatalardan biri şudur: SSL sertifikası ile private key birbirine uymuyor. Bu durumu cmp ile dolaylı olarak kontrol edebilirsiniz. Daha da iyi bir yaklaşım ise sertifika ve anahtarın modulus değerlerini karşılaştırmaktır:

#!/bin/bash
# ssl-check.sh - SSL sertifika ve anahtar uyum kontrolu

CERT_FILE="/etc/nginx/ssl/domain.crt"
KEY_FILE="/etc/nginx/ssl/domain.key"
BACKUP_CERT="/backup/ssl/domain.crt"
BACKUP_KEY="/backup/ssl/domain.key"

echo "=== SSL Dosyasi Karsilastirma ==="

# Mevcut sertifikayi backup ile karsilastir
if cmp -s "$CERT_FILE" "$BACKUP_CERT"; then
    echo "[OK] Sertifika backup ile ayni"
else
    echo "[UYARI] Sertifika degismis, yenilenme tarihi kontrol edilmeli"
    # Sadece ilk 100 byte'i karsilastir (header kontrolu)
    echo "Header karsilastirmasi:"
    cmp -n 100 "$CERT_FILE" "$BACKUP_CERT" 2>&1
fi

# Private key backup ile karsilastir
# DIKKAT: Bu islem sadece guvenli ortamda yapilmali!
if cmp -s "$KEY_FILE" "$BACKUP_KEY"; then
    echo "[OK] Private key backup ile ayni"
else
    echo "[KRITIK] Private key degismis! Acil inceleme gerekli!"
    exit 1
fi

Önemli not: Private key dosyalarını karşılaştırırken bu işlemin güvenli bir ortamda yapıldığından emin olun. Key dosyalarını asla network üzerinden düz metin olarak taşımayın.

Senaryo 3: Web Varlıklarının CDN Doğrulaması

Statik dosyalarınızı CDN’e yüklediniz. Peki CDN’deki dosyalar gerçekten doğru mu? Özellikle minify edilmiş JavaScript ve CSS dosyaları için bu kontrol kritiktir:

#!/bin/bash
# cdn-verify.sh - CDN uzerindeki dosyalari yerel kopya ile dogrula

LOCAL_ASSETS="/var/www/html/assets"
CDN_CACHE="/tmp/cdn-cache"
FAILED_FILES=0
CHECKED_FILES=0

# CDN'den dosyalari indir ve karsilastir
echo "=== CDN Dosya Dogrulama Baslıyor ==="

for local_file in "$LOCAL_ASSETS"/*.{js,css,woff2,png,jpg}; do
    [ -f "$local_file" ] || continue
    
    filename=$(basename "$local_file")
    cdn_file="$CDN_CACHE/$filename"
    
    # CDN'den dosyayi indir (wget veya curl ile)
    wget -q "https://cdn.siteniz.com/assets/$filename" -O "$cdn_file" 2>/dev/null
    
    if [ ! -f "$cdn_file" ]; then
        echo "[EKSIK] $filename CDN'de bulunamadi"
        ((FAILED_FILES++))
        continue
    fi
    
    if cmp -s "$local_file" "$cdn_file"; then
        echo "[OK] $filename eslesiyor"
    else
        echo "[HATA] $filename CDN'de farkli!"
        # Fark detaylarini goster
        LOCAL_SIZE=$(stat -c%s "$local_file")
        CDN_SIZE=$(stat -c%s "$cdn_file")
        echo "      Yerel boyut: $LOCAL_SIZE bytes, CDN boyut: $CDN_SIZE bytes"
        ((FAILED_FILES++))
    fi
    ((CHECKED_FILES++))
done

echo ""
echo "=== Sonuc ==="
echo "Kontrol edilen: $CHECKED_FILES dosya"
echo "Hata: $FAILED_FILES dosya"

[ $FAILED_FILES -eq 0 ] && exit 0 || exit 1

Senaryo 4: Çoklu Sunucu Konfigürasyon Senkronizasyonu

Load balancer arkasında 5 web sunucunuz var ve hepsinin aynı konfigürasyona sahip olması gerekiyor. Bu senaryoda cmp ile hızlı bir kontrol yapabilirsiniz:

#!/bin/bash
# multi-server-sync-check.sh
# Tum sunucularda nginx.conf esitligini kontrol eder

MASTER_SERVER="web01"
SERVERS=("web02" "web03" "web04" "web05")
CONFIG_PATH="/etc/nginx/nginx.conf"
TEMP_DIR="/tmp/config-check"
MASTER_CONFIG="$TEMP_DIR/nginx.conf.master"

mkdir -p "$TEMP_DIR"

# Master sunucudan konfig al
echo "Master sunucudan ($MASTER_SERVER) konfig alınıyor..."
scp -q "$MASTER_SERVER:$CONFIG_PATH" "$MASTER_CONFIG"

if [ $? -ne 0 ]; then
    echo "[HATA] Master sunucuya baglanılamadı!"
    exit 1
fi

echo "=== Konfigürasyon Esitlik Kontrolu ==="
ALL_OK=true

for server in "${SERVERS[@]}"; do
    REMOTE_CONFIG="$TEMP_DIR/nginx.conf.$server"
    
    # Uzak sunucudan konfig al
    scp -q "$server:$CONFIG_PATH" "$REMOTE_CONFIG" 2>/dev/null
    
    if [ $? -ne 0 ]; then
        echo "[UYARI] $server sunucusuna baglanılamadı, atlaniyor"
        continue
    fi
    
    if cmp -s "$MASTER_CONFIG" "$REMOTE_CONFIG"; then
        echo "[OK] $server - Master ile esit"
    else
        echo "[FARK] $server - Master ile FARKLI!"
        # Hangi byte'da farklilastigini goster
        FIRST_DIFF=$(cmp "$MASTER_CONFIG" "$REMOTE_CONFIG" 2>&1)
        echo "      İlk fark: $FIRST_DIFF"
        ALL_OK=false
    fi
    
    rm -f "$REMOTE_CONFIG"
done

rm -f "$MASTER_CONFIG"
rmdir "$TEMP_DIR" 2>/dev/null

echo ""
if $ALL_OK; then
    echo "Tum sunucular senkronize durumda."
    exit 0
else
    echo "Senkronizasyon sorunu tespit edildi!"
    exit 1
fi

İleri Düzey Kullanım

Byte Offset ile Kısmi Karşılaştırma

Bazen bir dosyanın sadece belirli bir bölümünü karşılaştırmanız gerekir. Örneğin bir binary’nin sadece header kısmını kontrol etmek istiyorsunuz:

# İlk 512 byte'ı karsilastir (MBR veya dosya header kontrolu)
cmp -n 512 dosya1.bin dosya2.bin

# Belirli bir offsetten baslayarak karsilastir
# dosya1'i 100. byte'tan, dosya2'yi 200. byte'tan baslayarak karsilastir
cmp -i 100:200 dosya1 dosya2

# Tum farkli byte'lari listele ve say
cmp -l dosya1 dosya2 | wc -l

# Farkli byte'larin detaylarini goster
cmp -lb dosya1 dosya2 | head -20

Pipe ile Kullanım

cmp stdin’den de okuyabilir. Bu özellik özellikle network üzerinden dosya kontrolü yaparken çok işe yarıyor:

# Uzak dosyayi indirmeden karsilastir
ssh web02 "cat /etc/nginx/nginx.conf" | cmp /etc/nginx/nginx.conf -

# gzip ile sikistirilmis bir dosyanin icerigini karsilastir
zcat backup.sql.gz | cmp - current.sql

# Hash ile birlikte kullanım
md5sum dosya1 dosya2
# Vs
cmp -s dosya1 dosya2 && echo "Aynı" || echo "Farklı"

cmp vs Diğer Araçlar

Hangi durumda hangisini kullanmalısınız?

  • cmp: Binary dosyalar, hızlı eşit/farklı kontrolü, byte düzeyinde detay gerektiğinde
  • diff: Metin dosyaları, ne değişti görmek istediğinizde, patch üretmek için
  • md5sum / sha256sum: Çok sayıda dosyayı hızlıca karşılaştırmak için, integrity kontrolü için
  • rsync --checksum: Dizinleri senkronize etmek ve farklılıkları bulmak için

Web sunucusu yönetiminde bu araçları birlikte kullanmak en verimli yaklaşımdır. Örneğin önce md5sum ile hızlı tarama yapıp, farklı bulunan dosyalarda cmp -l ile detaylı analiz yapabilirsiniz.

Exit Code’ları Anlama

cmp komutunun döndürdüğü exit code’ları script yazmada kritik öneme sahiptir:

  • 0: Dosyalar aynı
  • 1: Dosyalar farklı
  • 2: Hata oluştu (dosya bulunamadı, erişim engeli vb.)
cmp -s dosya1 dosya2
RESULT=$?

case $RESULT in
    0) echo "Dosyalar identik" ;;
    1) echo "Dosyalar farklı" ;;
    2) echo "Karşılaştırma hatası" ;;
esac

-s (silent) bayrağı ile birlikte bu pattern, script’lerinizde temiz ve güvenilir kontroller yapmanızı sağlar.

Pratik İpuçları

  • Büyük dosyalarda dikkatli olun: cmp -l ile büyük binary dosyaları karşılaştırırsanız çok fazla çıktı üretebilir. Çıktıyı head veya wc -l ile sınırlandırın.
  • Symbolic link’ler: cmp symlink’lerin işaret ettiği dosyaları karşılaştırır, symlink’lerin kendisini değil. Bu genellikle istediğiniz davranıştır ama bilinmesi gerekir.
  • İzin sorunları: cmp okuma iznine ihtiyaç duyar. Root ya da ilgili kullanıcı ile çalıştırın.
  • Cron job’larda kullanım: -s bayrağını her zaman kullanın, gereksiz mail/log çıktısından kaçının.
  • Paralel kontrol: Çok sayıda dosyayı kontrol ederken xargs -P ile paralel çalıştırarak süreci hızlandırabilirsiniz.

Sonuç

cmp komutu, web sunucusu yönetiminde göründüğünden çok daha fazla işe yarayan güçlü bir araçtır. Deployment doğrulamasından CDN kontrolüne, çoklu sunucu senkronizasyonundan SSL sertifika yönetimine kadar geniş bir kullanım alanına sahiptir.

En büyük avantajı şudur: Sizi yanıltmaz. Byte 0’dan başlayarak bit bit karşılaştırma yapar ve iki dosyanın gerçekten aynı olup olmadığını kesin olarak söyler. Metin editörlerinin gizleyebileceği boşluk karakterleri, satır sonu farklılıkları veya encoding sorunları cmp önünde gizlenemez.

Script’lerinizde cmp -s ile sessiz karşılaştırma yapın, exit code’lara göre aksiyonunuzu belirleyin. Bu basit pattern, çok sayıda production sorununu başlamadan önce engellemenizi sağlayacaktır.

Bir sonraki deployment’ınızda veya sunucu senkronizasyonunuzda cmp komutunu kullanmayı deneyin. Küçük bir araç, büyük güven verir.

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

diff komutu, iki metin dosyası arasındaki farkları satır satır karşılaştırarak gösterir. Web sunucusu yapılandırma dosyalarında yapılan değişiklikleri takip etmek ve sorunları tespit etmek için vazgeçilmez bir araçtır. Bu yazıda diff komutunun temel kullanımını ve pratik örneklerini bulabilirsiniz.

diff Komutu ile Dosya Farklarini Bulmak: Web Sunucusu Yonetiminde Pratik Rehber

Web sunucusu yonetirken kac kez “bu config dosyasinda ne degisti ki site coktu?” diye sordunuz kendinize? Ya da production ortaminda calisan bir nginx.conf ile staging’deki versiyonu karsilastirmaniz gerekti mi? Iste tam bu noktada diff komutu hayat kurtarici oluyor. Bu yazida diff komutunu web sunucusu yonetimi perspektifinden ele alacagiz, gercek dunya senaryolariyla pratik kullanim ornekleri goreceksiniz.

diff Nedir ve Neden Onemlidir?

diff (difference) komutu, iki dosya arasindaki farklari satir satir karsilastirip size gosteren bir Unix/Linux aracıdir. 1970’lerden bu yana var olan bu komut, basit gorunumune ragmen sistem yoneticisinin en kritik araclarindan biridir.

Web sunucusu yonetiminde diff komutunu en cok su durumlarda kullanirsiniz:

  • Apache veya Nginx yapilandirma dosyalarini karsilastirirken
  • Bir guncelleme oncesi ve sonrasi config farklarini analiz ederken
  • Backup dosyasiyla mevcut dosyayi karsilastirirken
  • Farkli ortamlar (dev, staging, production) arasindaki konfigurasyonlari inceleyken
  • Log dosyalarindaki beklenmedik degisiklikleri tespit ederken
  • Deployment sirasinda hangi dosyalarin degistigini anlayamadigimizda

Temel Kullanim Sontaksi

diff komutunun temel kullanimi son derece basittir:

diff [secenekler] dosya1 dosya2

Cikti okumak ilk basta biraz kafa karistiric gelebilir. Simdi bunu somutlastiralim. Diyelim ki iki basit nginx konfigurasyonunuz var.

eski_nginx.conf:

worker_processes 2;
keepalive_timeout 65;
gzip off;
server_name example.com;

yeni_nginx.conf:

worker_processes 4;
keepalive_timeout 75;
gzip on;
gzip_min_length 1000;
server_name example.com www.example.com;
diff eski_nginx.conf yeni_nginx.conf

Cikti soyle gorunur:

1c1
< worker_processes 2;
---
> worker_processes 4;
2c2
< keepalive_timeout 65;
---
> keepalive_timeout 75;
3c3,4
< gzip off;
---
> gzip on;
> gzip_min_length 1000;
4c5
< server_name example.com;
---
> server_name example.com www.example.com;

Bu ciktida:

  • < isareti birinci dosyadaki (eski) satiri gosterir
  • > isareti ikinci dosyadaki (yeni) satiri gosterir
  • c harfi “change” (degisim) anlamina gelir
  • a harfi “add” (ekleme) anlamina gelir
  • d harfi “delete” (silme) anlamina gelir

Unified Format: Cok Daha Okunabilir Cikti

Normal diff ciktisi biraz ham kalebilir. Web sunucusu configlerini incelerken genellikle unified format kullanmak cok daha mantiklidir. Bu format, git’in de kullandigi formattir ve degisikliklerin etrafindaki context satirlari da gosterir.

diff -u eski_nginx.conf yeni_nginx.conf

Cikti:

--- eski_nginx.conf    2024-01-15 10:23:45.000000000 +0300
+++ yeni_nginx.conf    2024-01-15 14:30:22.000000000 +0300
@@ -1,4 +1,5 @@
-worker_processes 2;
+worker_processes 4;
-keepalive_timeout 65;
+keepalive_timeout 75;
-gzip off;
+gzip on;
+gzip_min_length 1000;
 server_name example.com;
+server_name example.com www.example.com;

Bu formatta:

  • - ile baslayan satirlar eski dosyada var, yenide yok
  • + ile baslayan satirlar yeni dosyada var, eskide yok
  • Boslukla baslayan satirlar her iki dosyada da ayni sekilde mevcut (context)

-u parametresi yerine -U 5 kullanarak kac satir context gostermek istedigini de belirtebilirsiniz:

diff -U 5 eski_nginx.conf yeni_nginx.conf

Gercek Dunya Senaryosu 1: Apache Config Karsilastirma

Diyelim ki bir Apache guncelleme yaptiniz ve sitenin belirli URL’leri duzgun yonlendirmiyor. Backup’inizdaki .conf dosyasiyla mevcut dosyayi karsilastirmak istiyorsunuz.

# Backup dosyasi genellikle su konumlarda olur
diff -u /etc/apache2/sites-available/mysite.conf /etc/apache2/sites-available/mysite.conf.bak

# Ya da tarih damgali backup varsa
diff -u /etc/apache2/sites-available/mysite.conf /backup/apache/mysite.conf.20240115

Eger farklari bir dosyaya kaydetmek istiyorsaniz (ki bunu mutlaka yapmanizi tavsiye ederim):

diff -u /etc/apache2/sites-available/mysite.conf /backup/apache/mysite.conf.20240115 > /tmp/apache_config_diff.patch

# Dosyayi inceleyin
cat /tmp/apache_config_diff.patch

Bu .patch dosyasini daha sonra patch komutuyla uygulamak icin de kullanabilirsiniz, ama bu baska bir yazinin konusu.

Gercek Dunya Senaryosu 2: Dizin Karsilastirma

Web sunucunuzda /etc/nginx/conf.d/ dizinindeki tum config dosyalarini staging sunucusundakiyle karsilastirmak istiyorsunuz. diff komutu tek tek dosyalar icin degil, dizinler icin de calisir.

# Iki dizini recursive olarak karsilastir
diff -rq /etc/nginx/conf.d/ /backup/nginx/conf.d/

-r recursive (alt dizinleri de dahil et), -q ise quiet mode (sadece hangi dosyalarin farkli oldugunu goster, farklar detayli degil) anlamina gelir.

Cikti soyle gorunur:

Files /etc/nginx/conf.d/default.conf and /backup/nginx/conf.d/default.conf differ
Only in /etc/nginx/conf.d/: ssl.conf
Files /etc/nginx/conf.d/proxy.conf and /backup/nginx/conf.d/proxy.conf differ

Bu ciktidan hemen anliyoruz: ssl.conf dosyasi backup’ta yok, default.conf ve proxy.conf farkli. Simdi detaylari gorelim:

# Sadece farkli olan dosyayi detayli incele
diff -u /etc/nginx/conf.d/default.conf /backup/nginx/conf.d/default.conf

# Ya da tum dizini unified formatla karsilastir
diff -ru /etc/nginx/conf.d/ /backup/nginx/conf.d/

Gercek Dunya Senaryosu 3: SSL Sertifika Konfigurasyonu Kontrolu

SSL sertifika yenileme sonrasi Apache virtual host’un dogru guncellendi mi kontrol etmek istiyorsunuz. Eski ve yeni config arasindaki SSL ile ilgili satirlara odaklanmak istiyorsunuz.

# Temel karsilastirma
diff -u /etc/apache2/sites-available/ssl-site.conf.old /etc/apache2/sites-available/ssl-site.conf

# Sadece degisikliklerin sayisini gormek isterseniz
diff /etc/apache2/sites-available/ssl-site.conf.old /etc/apache2/sites-available/ssl-site.conf | wc -l

Bazen whitespace farkliliklari (bosluk, tab gibi) kafa karistirir. Bunlari ignore etmek icin:

# Whitespace farklarini yoksay
diff -u -b /etc/apache2/sites-available/ssl-site.conf.old /etc/apache2/sites-available/ssl-site.conf

# Bos satirlardaki whitespace farklarini da yoksay
diff -u -B /etc/apache2/sites-available/ssl-site.conf.old /etc/apache2/sites-available/ssl-site.conf

# Buyuk-kucuk harf farklarini da yoksay
diff -u -i /etc/apache2/sites-available/ssl-site.conf.old /etc/apache2/sites-available/ssl-site.conf

Gercek Dunya Senaryosu 4: Deployment Scripti ile Entegrasyon

Production deployment yapan bir script dusunun. Hangi config dosyalarinin degistigini log’a yazmak ve operatore bildirmek istiyorsunuz.

#!/bin/bash

# Deployment oncesi config farklarini kontrol eden script
OLD_CONFIG_DIR="/backup/configs/$(date -d 'yesterday' +%Y%m%d)"
NEW_CONFIG_DIR="/etc/nginx"
LOG_FILE="/var/log/deployment/config_diff_$(date +%Y%m%d_%H%M%S).log"

echo "Config farklari kontrol ediliyor..." | tee "$LOG_FILE"
echo "Tarih: $(date)" | tee -a "$LOG_FILE"
echo "==========================================" | tee -a "$LOG_FILE"

# Farkli dosyalari bul
DIFF_OUTPUT=$(diff -rq "$OLD_CONFIG_DIR" "$NEW_CONFIG_DIR" 2>/dev/null)

if [ -z "$DIFF_OUTPUT" ]; then
    echo "Hicbir config dosyasinda degisiklik yok." | tee -a "$LOG_FILE"
else
    echo "Degisen dosyalar:" | tee -a "$LOG_FILE"
    echo "$DIFF_OUTPUT" | tee -a "$LOG_FILE"
    echo "" | tee -a "$LOG_FILE"

    # Her farkli dosya icin detayli diff al
    while IFS= read -r line; do
        if [[ "$line" == Files* ]]; then
            FILE1=$(echo "$line" | awk '{print $2}')
            FILE2=$(echo "$line" | awk '{print $4}')
            echo "--- Detayli fark: $FILE1 ---" | tee -a "$LOG_FILE"
            diff -u "$FILE1" "$FILE2" | tee -a "$LOG_FILE"
            echo "" | tee -a "$LOG_FILE"
        fi
    done <<< "$DIFF_OUTPUT"

    echo "Log dosyasi kaydedildi: $LOG_FILE"
fi

Bu script sayesinde her deployment’ta hangi config’in nasil degistigine dair tam bir kayit tutulmus olur.

Renk ve Gorsel Gelistirmeler: colordiff

Terminal’de renksiz diff ciktisi okumak yorucu olabilir. colordiff aracini yukleyerek cok daha okunabilir bir deneyim elde edebilirsiniz.

# Ubuntu/Debian
sudo apt install colordiff

# CentOS/RHEL
sudo yum install colordiff

# Kullanim aynı diff gibi
colordiff -u /etc/nginx/nginx.conf /backup/nginx/nginx.conf.bak

~/.bashrc veya ~/.bash_aliases dosyasina ekleyerek diff komutunu otomatik olarak renkli hale getirebilirsiniz:

alias diff='colordiff'

Cikti Formatlarini Karsilastirma

diff komutu farkli cikti formatlari destekler. Web sunucusu yonetiminde en cok kullandiginiz formatlar sunlar olacaktir:

  • Normal format (varsayilan): Eski, minimal cikti. Script’lerde parse etmek icin uygun.
  • Unified format (-u): En okunakli format, git de bu formati kullanir. Insan okumasi icin ideal.
  • Context format (-c): Unified’a benzer ama biraz farkli gorunum. Legacy sistem uyumlulugu icin kullanilir.
  • Side by side (-y): Iki dosyayi yan yana gosterir. Genis terminal’de cok kullanisli.
# Side by side karsilastirma
diff -y --width=200 /etc/nginx/nginx.conf /backup/nginx/nginx.conf.bak

# Side by side, sadece farkli satirlari goster
diff -y --suppress-common-lines /etc/nginx/nginx.conf /backup/nginx/nginx.conf.bak

diff ile Binarileri ve Ozet Karsilastirma

Config dosyasi gibi gorunen ama aslinda binary olan (ornegin SSL private key .der formati) ya da cok buyuk log dosyalarini karsilastirirken ozet yontem ise yarar. Burada md5sum veya sha256sum ile kombine kullanmak pratiktir.

# Iki dosyanin hash'ini karsilastir (icerik ayni mi diye bak)
md5sum /etc/nginx/nginx.conf /backup/nginx/nginx.conf.bak

# Ya da dogrudan diff ile binary dosyalari karsilastir (farkli mi degil mi sorar)
diff <(md5sum /etc/nginx/nginx.conf) <(md5sum /backup/nginx/nginx.conf.bak)

Pratik Ipuclari ve Kisayollar

Gunluk is hayatinda isinizi kolaylastiracak birkac ipucu:

Geri donus kodu kontrolu: diff komutu fark buldugunda 1, bulamadiginda 0, hata olustugunda 2 doner. Bunu script’lerde kullanabilirsiniz.

diff dosya1 dosya2
if [ $? -eq 0 ]; then
    echo "Dosyalar ayni"
elif [ $? -eq 1 ]; then
    echo "Dosyalar farkli"
fi

Process substitution ile canli karsilastirma: Bir komutun ciktisini dosyayla karsilastirmak istediginizde:

# Mevcut nginx config ile parse edilmis halini karsilastir
diff <(nginx -T 2>/dev/null | grep -v '#') /etc/nginx/nginx.conf

Recursive, sadece belirli uzantilar: Tum dizini degil, sadece .conf dosyalarini karsilastirmak icin:

# find ile birlikte kullanin
find /etc/nginx -name "*.conf" -exec sh -c 'diff -u "$1" "/backup/nginx${1#/etc/nginx}" 2>/dev/null' _ {} ;

Sonuc

diff komutu, web sunucusu yonetiminin vazgecilmez bir parcasidir. Nginx veya Apache config dosyalarindaki beklenmedik degisiklikleri tespit etmek, deployment oncesi ve sonrasi karsilastirma yapmak, backup kontrolu saglamak gibi pek cok kritik gorevde bu komutu kullanacaksiniz.

En onemli cikartim: diff -u formatini alisinkanlik haline getirin. Unified format hem okunabilir hem de patch komutuyla dogrudan uygulanabilir oldugu icin en pratik secenektir.

Buyuk bir degisiklik yapmadan once her zaman mevcut config’in bir kopyasini alin ve degisiklik sonrasi diff ile karsilastirmayi ihmal etmeyin. Gece 2’de production’da yarim saatlik kesintiye neden olan “kucuk bir bosluk hatasi”nin acisini yasamak istemiyorsaniz, diff komutunu is akisinizin standart bir parcasi haline getirin.

Bir sonraki yazida patch komutuyla diff ciktisini nasil uygulayacagimizi ve bu ikilinin CI/CD pipeline’larinda nasil kullanildigini ele alacagiz.