gzip ile Dosya Sıkıştırma ve Açma

Sistem yöneticiliğinde disk alanı her zaman değerli bir kaynaktır. Log dosyaları şişer, yedekler büyür, transfer edilecek dosyalar bant genişliğini tıkar. İşte tam bu noktada gzip devreye girer. Yıllardır Linux dünyasının vazgeçilmezi olan bu araç, basit görünümünün arkasında oldukça güçlü bir sıkıştırma motoru barındırır. Bu yazıda gzip komutunu her yönüyle ele alacağız; temel kullanımdan ileri düzey senaryolara, log yönetiminden otomatik yedekleme scriptlerine kadar her şeyi konuşacağız.

gzip Nedir ve Nasıl Çalışır?

gzip, GNU zip’in kısaltmasıdır ve DEFLATE algoritmasını kullanır. Bu algoritma LZ77 ve Huffman kodlamasını birleştirir. Tekrar eden byte dizilerini referans göstererek sıkıştırır, yani metin tabanlı dosyalarda (log dosyaları, CSV, XML, JSON) çok daha iyi sonuçlar verir. Binary dosyalarda ise verim biraz düşer ama yine de kayda değer bir küçülme sağlar.

gzip‘in en önemli özelliklerinden biri kayıpsız (lossless) sıkıştırma yapmasıdır. Yani sıkıştırıp tekrar açtığınızda dosya birebir aynı kalır. Production ortamlarında bu kritik bir gereksinimdir.

Kurulum ve Temel Kontrol

Çoğu Linux dağıtımında gzip zaten kurulu gelir. Ama bazı minimal kurulumlar veya container imajları bunu içermeyebilir.

# Kurulu mu kontrol et
which gzip
gzip --version

# Ubuntu/Debian'da kurulum
sudo apt-get install gzip

# RHEL/CentOS/Rocky Linux'ta kurulum
sudo yum install gzip
# veya
sudo dnf install gzip

Temel Kullanım: Dosya Sıkıştırma

gzip‘in en basit kullanımı bir dosyanın adını argüman olarak vermektir. Ancak burada dikkat edilmesi gereken önemli bir nokta var: gzip orijinal dosyayı siler ve yerine .gz uzantılı sıkıştırılmış versiyonu bırakır.

# Tek bir dosyayı sıkıştır
gzip access.log

# Sonuç: access.log silinir, access.log.gz oluşur
ls -lh access.log.gz

Bu davranış yeni başlayanları sık sık şaşırtır. Orijinal dosyayı korumak istiyorsanız -k parametresini kullanmanız gerekir.

# Orijinal dosyayı koru
gzip -k access.log

# Artık hem access.log hem de access.log.gz var
ls -lh access.log access.log.gz

Birden fazla dosyayı aynı anda sıkıştırmak için wildcard kullanabilirsiniz:

# Tüm log dosyalarını sıkıştır
gzip /var/log/nginx/*.log

# Belirli bir pattern'e uyan dosyaları sıkıştır
gzip /var/backups/db_backup_2024*.sql

Dosya Açma: Decompress İşlemi

Sıkıştırılmış bir dosyayı açmak için -d parametresini ya da gunzip komutunu kullanabilirsiniz. Her ikisi de aynı işi yapar.

# Birinci yöntem: gzip -d
gzip -d access.log.gz

# İkinci yöntem: gunzip (tamamen aynı şey)
gunzip access.log.gz

# Orijinal .gz dosyasını koruyarak aç
gunzip -k access.log.gz
# veya
gzip -dk access.log.gz

zcat komutu ise dosyayı diske yazmadan içeriğini doğrudan ekrana basar. Log analizi yaparken bu çok işe yarar:

# Dosyayı açmadan içeriğini gör
zcat access.log.gz

# grep ile birleştir
zcat access.log.gz | grep "ERROR"

# Satır sayısını öğren
zcat access.log.gz | wc -l

Sıkıştırma Seviyeleri

gzip 1’den 9’a kadar sıkıştırma seviyesi sunar. 1 en hızlı ama en az sıkıştırma, 9 en yavaş ama en fazla sıkıştırma anlamına gelir. Varsayılan değer 6‘dır ve çoğu senaryo için iyi bir denge noktasıdır.

# En hızlı sıkıştırma (level 1)
gzip -1 büyük_dosya.log

# Varsayılan sıkıştırma (level 6)
gzip büyük_dosya.log

# Maksimum sıkıştırma (level 9)
gzip -9 büyük_dosya.log

# --fast ve --best kısayolları
gzip --fast büyük_dosya.log   # -1 ile aynı
gzip --best büyük_dosya.log   # -9 ile aynı

Peki hangi seviyeyi seçmelisiniz? Şöyle düşünün:

  • Level 1-3: Gerçek zamanlı log sıkıştırma, çok büyük dosyalar, CPU’nun değerli olduğu ortamlar
  • Level 6: Günlük yedeklemeler, genel amaçlı kullanım
  • Level 7-9: Uzun vadeli arşivler, ağ üzerinden aktarım öncesi, disk alanının kritik olduğu durumlar

Önemli Parametreler

gzip‘in sık kullandığınız parametrelerini şöyle özetleyebilirim:

-d: Dosyayı aç (decompress), gunzip ile eşdeğer

-k: Orijinal dosyayı koru, sil

-l: Sıkıştırılmış dosya hakkında bilgi göster (compression ratio dahil)

-r: Dizinleri recursive olarak işle

-v: Verbose mod, sıkıştırma oranını gösterir

-t: Dosyanın bütünlüğünü test et

-c: Çıktıyı stdout’a yaz, orijinal dosyayı değiştirme

-f: Zorla üzerine yaz, varolan dosyaları atla

-S: Farklı bir suffix (uzantı) kullan

-n: Orijinal dosya adını ve zaman damgasını kaydetme

-N: Orijinal dosya adını ve zaman damgasını kaydet (varsayılan)

Dosya Bilgisi ve Bütünlük Testi

Production ortamında sıkıştırılmış dosyaların bozulup bozulmadığını kontrol etmek kritik önem taşır. gzip -l ve gzip -t bu konuda hayat kurtarır.

# Sıkıştırma bilgilerini görüntüle
gzip -l access.log.gz

# Çıktı şöyle görünür:
# compressed  uncompressed  ratio uncompressed_name
#    2847632      18432016  84.5% access.log

# Verbose modda daha fazla bilgi
gzip -lv access.log.gz

# Dosya bütünlüğünü test et
gzip -t access.log.gz
echo $?  # 0 ise dosya sağlıklı, 0 değilse bozuk

# Birden fazla dosyayı test et
gzip -t /var/backups/*.gz

# Test ve verbose birlikte
gzip -tv /var/backups/*.gz

Otomatik script’lerde bu kontrolü şöyle kullanabilirsiniz:

#!/bin/bash
# Yedek dosyalarının bütünlüğünü kontrol et

BACKUP_DIR="/var/backups"
FAILED_COUNT=0

for gz_file in ${BACKUP_DIR}/*.gz; do
    if ! gzip -t "$gz_file" 2>/dev/null; then
        echo "HATA: $gz_file bozuk!" >&2
        FAILED_COUNT=$((FAILED_COUNT + 1))
    else
        echo "OK: $gz_file"
    fi
done

if [ $FAILED_COUNT -gt 0 ]; then
    echo "Toplam $FAILED_COUNT bozuk dosya bulundu!"
    exit 1
fi

echo "Tüm yedek dosyaları sağlıklı."
exit 0

Pipe ile Kullanım: Gerçek Güç Burada

gzip‘in gerçek gücü pipe kullanımında ortaya çıkar. -c parametresi çıktıyı stdout’a yönlendirir, bu da gzip‘i diğer komutlarla zincire bağlamanızı sağlar.

# tar ile birlikte kullan
tar -cvf - /var/www/html | gzip -9 > website_backup.tar.gz

# Veritabanı yedeği al ve sıkıştır
mysqldump -u root -p mydb | gzip -6 > mydb_$(date +%Y%m%d).sql.gz

# PostgreSQL yedeği
pg_dump mydb | gzip > mydb_backup.gz

# Uzak sunucuya sıkıştırarak aktar
tar -cvf - /data/important | gzip | ssh user@backup-server "cat > /backups/important.tar.gz"

# Sıkıştırılmış yedeği uzaktan çöz
ssh user@backup-server "cat /backups/important.tar.gz" | gunzip | tar -xvf -

Recursive Dizin Sıkıştırma

-r parametresi ile bir dizin altındaki tüm dosyaları recursive olarak sıkıştırabilirsiniz. Ancak bu yöntemin bir dezavantajı var: dizin yapısını korumaz, her dosyayı ayrı ayrı sıkıştırır. Dizin yapısını da korumak istiyorsanız tar ile birleştirmeniz gerekir.

# Bir dizindeki tüm dosyaları recursive sıkıştır
gzip -r /var/log/apache2/

# Verbose modda
gzip -rv /var/log/nginx/

# Dizin yapısını koruyarak sıkıştır (tar ile)
tar -czvf logs_archive.tar.gz /var/log/nginx/

Gerçek Dünya Senaryosu 1: Log Rotasyon Otomasyonu

Sistem yöneticilerinin en sık karşılaştığı sorunlardan biri büyüyen log dosyalarıdır. İşte gzip‘i kullanarak log dosyalarını otomatik olarak arşivleyen bir script:

#!/bin/bash
# log_archive.sh - Eski log dosyalarını sıkıştır

LOG_DIR="/var/log/myapp"
ARCHIVE_DIR="/var/log/myapp/archive"
DAYS_OLD=7
COMPRESSION_LEVEL=6

# Arşiv dizini yoksa oluştur
mkdir -p "$ARCHIVE_DIR"

echo "Log arşivleme başlıyor: $(date)"

# 7 günden eski .log dosyalarını bul ve sıkıştır
find "$LOG_DIR" -maxdepth 1 -name "*.log" -mtime +${DAYS_OLD} | while read log_file; do
    filename=$(basename "$log_file")
    
    echo "Sıkıştırılıyor: $filename"
    
    # Sıkıştır ve arşiv dizinine taşı
    gzip -${COMPRESSION_LEVEL} -c "$log_file" > "${ARCHIVE_DIR}/${filename}.gz"
    
    # Sıkıştırma başarılı ise orijinali sil
    if [ $? -eq 0 ]; then
        rm "$log_file"
        echo "Tamamlandı: ${filename}.gz"
    else
        echo "HATA: $filename sıkıştırılamadı!" >&2
        rm -f "${ARCHIVE_DIR}/${filename}.gz"
    fi
done

# 30 günden eski arşivleri sil
find "$ARCHIVE_DIR" -name "*.gz" -mtime +30 -delete
echo "Log arşivleme tamamlandı: $(date)"

Gerçek Dünya Senaryosu 2: Veritabanı Yedekleme Pipeline’ı

Çoğu ortamda veritabanı yedekleri hem büyük hem de ağ üzerinden transfer edilmesi gereken dosyalardır. Sıkıştırma burada çift fayda sağlar: disk alanı ve transfer süresi.

#!/bin/bash
# db_backup.sh - MySQL veritabanlarını sıkıştırarak yedekle

BACKUP_DIR="/var/backups/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_USER="backup_user"
MYSQL_PASS="güvenli_parola"
REMOTE_SERVER="backup.company.com"
REMOTE_DIR="/backups/db"
RETENTION_DAYS=14

mkdir -p "$BACKUP_DIR"

# Tüm veritabanlarını listele (sistem DB'leri hariç)
databases=$(mysql -u "$MYSQL_USER" -p"$MYSQL_PASS" -e "SHOW DATABASES;" 2>/dev/null | 
    grep -Ev "^(Database|information_schema|performance_schema|mysql|sys)$")

for db in $databases; do
    backup_file="${BACKUP_DIR}/${db}_${DATE}.sql.gz"
    
    echo "Yedekleniyor: $db"
    
    # Dump al, sıkıştır, doğrula
    mysqldump -u "$MYSQL_USER" -p"$MYSQL_PASS" 
        --single-transaction 
        --routines 
        --triggers 
        "$db" 2>/dev/null | gzip -6 > "$backup_file"
    
    # Dosya bütünlüğü kontrolü
    if gzip -t "$backup_file" 2>/dev/null; then
        SIZE=$(du -sh "$backup_file" | cut -f1)
        echo "$db yedeği tamamlandı. Boyut: $SIZE"
        
        # Uzak sunucuya kopyala
        rsync -az "$backup_file" "${REMOTE_SERVER}:${REMOTE_DIR}/" && 
            echo "$db uzak sunucuya aktarıldı."
    else
        echo "HATA: $db yedeği bozuk!" >&2
        rm -f "$backup_file"
    fi
done

# Eski yedekleri temizle
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +${RETENTION_DAYS} -delete
echo "Temizleme tamamlandı: $RETENTION_DAYS günden eski yedekler silindi."

zgrep, zless ve zmore: Sıkıştırılmış Dosyalarla Çalışmak

gzip ekosistemi sadece sıkıştırma ve açmadan ibaret değil. Sıkıştırılmış dosyalarda doğrudan arama yapmanızı ve içerik görüntülemenizi sağlayan yardımcı araçlar da var.

# Sıkıştırılmış log içinde arama yap
zgrep "ERROR" /var/log/syslog.gz
zgrep -i "critical" /var/log/apache2/error.log.gz

# Birden fazla sıkıştırılmış dosyada arama
zgrep "failed password" /var/log/auth.log*.gz

# Sayfalı görüntüleme
zless /var/log/messages.gz
zmore /var/log/kern.log.gz

# İki sıkıştırılmış dosyayı karşılaştır
zdiff dosya1.gz dosya2.gz

# Sıkıştırılmış dosyaları birleştir
zcat log1.gz log2.gz log3.gz > merged.log
zcat log1.gz log2.gz | gzip > merged.log.gz

Performans Karşılaştırması ve Doğru Seviye Seçimi

Gerçek bir ortamda farklı sıkıştırma seviyelerinin etkisini görmek için bu komutu kullanabilirsiniz:

#!/bin/bash
# compression_benchmark.sh - Sıkıştırma seviyelerini karşılaştır

TEST_FILE="$1"

if [ -z "$TEST_FILE" ] || [ ! -f "$TEST_FILE" ]; then
    echo "Kullanım: $0 <test_dosyası>"
    exit 1
fi

ORIGINAL_SIZE=$(stat -c%s "$TEST_FILE")
echo "Orijinal boyut: $(du -sh "$TEST_FILE" | cut -f1)"
echo "---"

for level in 1 3 6 9; do
    START_TIME=$(date +%s%N)
    gzip -${level} -k -c "$TEST_FILE" > "/tmp/test_level${level}.gz"
    END_TIME=$(date +%s%N)
    
    COMPRESSED_SIZE=$(stat -c%s "/tmp/test_level${level}.gz")
    ELAPSED=$(( (END_TIME - START_TIME) / 1000000 ))
    RATIO=$(echo "scale=1; (1 - $COMPRESSED_SIZE / $ORIGINAL_SIZE) * 100" | bc)
    
    echo "Level $level: $(du -sh /tmp/test_level${level}.gz | cut -f1) | Oran: %${RATIO} | Süre: ${ELAPSED}ms"
    rm -f "/tmp/test_level${level}.gz"
done

Sık Karşılaşılan Sorunlar ve Çözümleri

Dosya zaten .gz uzantılı ama açılmıyor: Bazen dosyalar .gz uzantısı alır ama gerçekte sıkıştırılmamıştır. file komutuyla kontrol edin:

file şüpheli_dosya.gz
# Eğer "gzip compressed data" yazıyorsa gerçek bir gzip dosyası
# "ASCII text" veya başka bir şey yazıyorsa uzantı aldatıcıdır

“gzip: stdout: Broken pipe” hatası: Bu aslında bir hata değil, pipe’ın karşı tarafının (örneğin head) veriyi almayı bırakmasından kaynaklanır. 2>/dev/null ile bastırabilirsiniz:

zcat büyük_dosya.gz 2>/dev/null | head -100

Disk alanı yetersizliği: gzip sıkıştırırken geçici olarak hem orijinal hem de sıkıştırılmış dosyayı disk üzerinde tutar. Disk doluysa -c ve yönlendirme kullanın:

# Farklı bir diskteki hedefe sıkıştır
gzip -c /disk1/büyük_dosya.log > /disk2/büyük_dosya.log.gz

Cron ile Otomatik Sıkıştırma

Production sistemlerde tüm bu işlemleri cron ile otomatize etmek standart bir pratiktir:

# crontab -e ile ekle

# Her gece 02:00'da log dosyalarını sıkıştır
0 2 * * * /usr/local/bin/log_archive.sh >> /var/log/log_archive.log 2>&1

# Her Pazar 03:00'da veritabanı yedeği al
0 3 * * 0 /usr/local/bin/db_backup.sh >> /var/log/db_backup.log 2>&1

# Her ayın 1'inde eski arşivleri temizle
0 4 1 * * find /var/backups -name "*.gz" -mtime +90 -delete

gzip mi, bzip2 mi, xz mi?

Bu soruyu sormayan sysadmin yoktur. Kısa cevap: duruma göre değişir.

  • gzip: En hızlı, yaygın uyumluluk, iyi sıkıştırma oranı. Log rotasyon, pipeline işlemleri, hız kritikse tercih edin.
  • bzip2: gzip’ten yavaş ama daha iyi sıkıştırma. .bz2 ve bunzip2 ile kullanılır.
  • xz: En yüksek sıkıştırma oranı ama en yavaş. Uzun vadeli arşivler, dağıtım paketleri için ideal.

Günlük operasyonel işler için gzip neredeyse her zaman doğru seçimdir. Hız/oran dengesi mükemmeldir ve her sistemde varsayılan olarak bulunur.

Sonuç

gzip, Linux sistem yönetiminin temel taşlarından biridir. Basit görünümünün arkasında yıllarca üretim ortamlarında güvenilirliğini kanıtlamış sağlam bir araç yatmaktadır. Log dosyalarını sıkıştırmaktan veritabanı yedeklerine, uzak sunuculara veri aktarımından otomatik arşivleme pipeline’larına kadar her yerde karşınıza çıkar.

Bu yazıda ele aldığımız kavramları şöyle özetleyebiliriz: temel sıkıştırma ve açma işlemleri, sıkıştırma seviyeleri ve performans dengesi, pipe ile güçlü kombinasyonlar, bütünlük kontrolü ve doğrulama, gerçek dünya senaryoları için production-ready scriptler.

Özellikle -t ile bütünlük kontrolü ve pipe kullanımı alışkanlık edinilmesi gereken pratiklerdir. Bir yedek dosyası açılmaz hale geldiğinde bunu öğrenmek için en kötü an, tam ihtiyaç duyduğunuz andır. gzip -t komutu ise bu sürprizi cron job’a çevirir, sizi önceden uyarır.

zgrep, zless ve zcat gibi yardımcı araçları da repertuarınıza katın; sıkıştırılmış log dosyalarını açıp aramak yerine doğrudan üzerinde çalışmak hem zaman kazandırır hem de disk alanından tasarruf sağlar. gzip küçük bir araç ama doğru kullanıldığında sistem yönetiminde çok büyük bir fark yaratır.

Yorum yapın