Disk alanı her zaman yetmez. Özellikle büyük log dosyaları, veritabanı yedekleri ya da uzun süreli arşivler söz konusu olduğunda, gzip ile elde ettiğin sıkıştırma oranı seni tatmin etmeyebilir. İşte tam bu noktada bzip2 ve xz devreye giriyor. Bu iki araç, daha yüksek sıkıştırma oranı sunmak için daha fazla CPU ve bellek harcıyor, ama sonuçlar çoğu zaman bu maliyeti fazlasıyla karşılıyor. Bu yazıda her iki aracı da derinlemesine inceleyeceğiz, gerçek dünya senaryolarında nasıl kullandığımı paylaşacağım ve hangisini ne zaman tercih etmen gerektiğini netleştireceğim.
bzip2 Nedir ve Nasıl Çalışır?
bzip2, Burrows-Wheeler algoritmasını kullanarak veriyi sıkıştırır. gzip‘in kullandığı DEFLATE algoritmasından farklı olarak, bu yöntem blok bazlı çalışır ve genellikle metin tabanlı veriler, log dosyaları ve kaynak kodlar üzerinde çok daha iyi sonuçlar verir.
Tarihsel olarak bakarsak, bzip2 uzun yıllar boyunca Linux dünyasında “ciddi sıkıştırma” demekti. Kernel tarball’ları, büyük veritabanı dökümleri, önemli yedekler… hepsi bzip2 ile sıkıştırılırdı. Günümüzde xz onun yerini büyük ölçüde aldı, ama bzip2 hâlâ birçok ortamda aktif olarak kullanılıyor.
Temel bzip2 Kullanımı
# Tek bir dosyayı sıkıştır
bzip2 dosya.txt
# Sıkıştırma tamamlandığında orijinal dosya silinir, dosya.txt.bz2 oluşur
ls -lh dosya.txt.bz2
# Açmak için
bunzip2 dosya.txt.bz2
# Ya da bzip2 -d ile
bzip2 -d dosya.txt.bz2
Burada dikkat etmen gereken ilk şey: bzip2 varsayılan olarak orijinal dosyayı siliyor. Eğer orijinal dosyayı korumak istiyorsan -k (keep) parametresini kullanmalısın.
# Orijinal dosyayı koruyarak sıkıştır
bzip2 -k access.log
# Şimdi hem access.log hem de access.log.bz2 mevcut
ls -lh access.log access.log.bz2
bzip2 Parametreleri
- -1 ile -9: Sıkıştırma seviyesi. -1 en hızlı ama en düşük oran, -9 en yavaş ama en yüksek oran. Varsayılan -9’dur
- -k: Orijinal dosyayı sil, yani “keep” modunda çalış
- -d: Decompress, yani dosyayı aç
- -v: Verbose, işlem detaylarını göster
- -t: Test, arşivin bütünlüğünü kontrol et ama açma
- -f: Force, hedef dosya varsa üzerine yaz
- -z: Açıkça sıkıştırma modunu belirt (varsayılan zaten bu)
- -c: Çıktıyı stdout’a yaz, dosyayı değiştirme
- -q: Quiet, gereksiz mesajları bastır
Gerçek dünyada log rotasyonu yaparken şöyle bir şey yazarım:
# /var/log/nginx altındaki tüm .log dosyalarını sıkıştır
for f in /var/log/nginx/*.log.1; do
bzip2 -9 -v "$f"
done
# Ya da find ile daha temiz bir şekilde
find /var/log/nginx -name "*.log.1" -exec bzip2 -9 {} ;
xz: Modern ve Güçlü
xz, LZMA2 algoritmasını kullanır ve günümüzde mevcut en iyi genel amaçlı sıkıştırma araçlarından biri kabul edilir. Linux kernel’ının kaynak kodu artık .tar.xz formatında dağıtılıyor. Debian paket sistemi, büyük arşivler için xz kullanıyor. Fedora ve diğer dağıtımlar RPM paketlerinde xz sıkıştırması tercih ediyor.
Neden bu kadar popüler? Çünkü aynı veri için gzip‘e kıyasla %30-70 daha küçük dosyalar üretiyor. Evet, daha yavaş, ama bir kez sıkıştırıp defalarca aktarıyorsan bu hız farkı önemini kaybediyor.
Temel xz Kullanımı
# Tek dosyayı sıkıştır
xz dosya.txt
# dosya.txt.xz oluşur, orijinal silinir
# Orijinali koruyarak sıkıştır
xz -k veritabani_yedek.sql
# Açmak için
xz -d dosya.txt.xz
# ya da
unxz dosya.txt.xz
# Verbose modda sıkıştırma oranını gör
xz -v -k büyük_dosya.tar
xz Parametreleri
- -0 ile -9: Sıkıştırma seviyesi. -6 varsayılandır, -9 maksimum sıkıştırma
- -e: Extreme mod, aynı seviyede daha fazla CPU harcayarak biraz daha iyi sonuç alır
- -k: Keep, orijinal dosyayı koru
- -d: Decompress
- -v: Verbose, ilerleme ve istatistikleri göster
- -T: Thread sayısı, çok çekirdekli CPU kullanımı için
- -l: Liste, arşiv içeriğini göster
- -t: Test, bütünlük kontrolü
- -c: stdout’a yaz
- -f: Force, üzerine yaz
- –memlimit: Bellek kullanım limiti belirle
Yüksek sıkıştırma seviyeleri ciddi bellek tüketebilir. -9 -e kombinasyonu gigabaytlarca RAM kullanabilir. Bunu production sunucuda dikkatsizce çalıştırmak istemezsin.
# Bellek limitli sıkıştırma
xz -9 -T 4 --memlimit=2GiB yedek.tar
# Çok çekirdekli sıkıştırma (4 thread)
xz -6 -T 4 -v büyük_arşiv.tar
tar ile Birlikte Kullanım
Pratikte bzip2 ve xz‘yi genellikle tar ile birlikte kullanırsın. Tek tek dosyalar için direkt komutlar yeterliyken, dizin ağaçlarını arşivlemek için tar şart.
# tar + bzip2 kombinasyonu
tar -cjvf yedek.tar.bz2 /var/www/html/
# tar + xz kombinasyonu
tar -cJvf yedek.tar.xz /var/www/html/
# Açmak
tar -xjvf yedek.tar.bz2
tar -xJvf yedek.tar.xz
# İçeriği listelemek (açmadan)
tar -tjf yedek.tar.bz2
tar -tJf yedek.tar.xz
Burada j parametresi bzip2’yi, J parametresi xz’yi temsil ediyor. Büyük harf-küçük harf farkına dikkat et.
Gerçek Dünya: Veritabanı Yedekleme Scripti
Bir müşteri sunucusunda her gece çalışan, MySQL yedeklerini sıkıştırarak S3’e gönderen bir script kullanıyoruz. Bu senaryoda dosya boyutu doğrudan bant genişliği maliyetini etkiliyor, bu yüzden xz tercihimiz:
#!/bin/bash
# mysql_backup.sh
TARIH=$(date +%Y%m%d_%H%M%S)
YEDEK_DIZIN="/tmp/yedekler"
DB_ADI="uygulama_db"
S3_BUCKET="s3://sirket-yedekler/mysql/"
mkdir -p "$YEDEK_DIZIN"
# Veritabanını dök
mysqldump
--single-transaction
--routines
--triggers
"$DB_ADI" > "$YEDEK_DIZIN/${DB_ADI}_${TARIH}.sql"
# xz ile sıkıştır, 4 thread kullan
xz -6 -T 4 -v "$YEDEK_DIZIN/${DB_ADI}_${TARIH}.sql"
# S3'e gönder
aws s3 cp
"$YEDEK_DIZIN/${DB_ADI}_${TARIH}.sql.xz"
"${S3_BUCKET}"
# Lokal dosyayı temizle
rm -f "$YEDEK_DIZIN/${DB_ADI}_${TARIH}.sql.xz"
echo "Yedekleme tamamlandı: ${DB_ADI}_${TARIH}.sql.xz"
Bu scriptle, 800 MB’lık bir SQL dump’ı genellikle 120-150 MB’a düşürüyoruz. Aylık yüzlerce yedek birikiyor ve bu fark çok ciddi bir depolama tasarrufu sağlıyor.
Sıkıştırma Oranı Karşılaştırması
Teorik konuşmak yerine gerçek testlerden bahsedelim. Aynı 1 GB’lık MySQL dump dosyası üzerinde:
# Test dosyasını hazırla
cp büyük_dump.sql /tmp/test_dump.sql
# gzip testi
time gzip -9 -k /tmp/test_dump.sql
# bzip2 testi
time bzip2 -9 -k /tmp/test_dump.sql
# xz testi
time xz -6 -k /tmp/test_dump.sql
# Sonuçları gör
ls -lh /tmp/test_dump.sql*
Tipik sonuçlar büyük ölçüde veri tipine göre değişse de genel eğilim şu yönde olur:
gzip -9: Orijinalin yaklaşık %35-40’ı kadarbzip2 -9: Orijinalin yaklaşık %28-35’i kadarxz -6: Orijinalin yaklaşık %22-28’i kadar
Zaman açısından ise gzip saniyeler içinde bitirirken, bzip2 birkaç dakika, xz ise daha uzun sürebilir. Ama bu rakamlar CPU’ya, thread ayarlarına ve veri tipine göre dramatik şekilde değişir.
pbzip2 ve pixz: Paralel Sıkıştırma
bzip2 ve xz‘nin en büyük dezavantajı yavaşlıklarıdır. Ama modern sunucularda onlarca çekirdek var ve bu çekirdekleri kullanmak için paralel versiyonlar mevcut.
pbzip2 (Parallel bzip2):
# pbzip2 kur
apt install pbzip2 # Debian/Ubuntu
yum install pbzip2 # RHEL/CentOS
# Tüm CPU çekirdeklerini kullan
pbzip2 -9 büyük_dosya.tar
# Manuel thread sayısı
pbzip2 -9 -p8 büyük_dosya.tar
# tar ile birlikte
tar -c /veri/dizin | pbzip2 -9 > arşiv.tar.bz2
pixz (Parallel xz):
# pixz kur
apt install pixz
# Sıkıştır
pixz -9 büyük_dosya.tar
# tar pipeline ile
tar -c /veri/dizin | pixz -9 > arşiv.tar.xz
# Açarken de hızlı
pixz -d arşiv.tar.xz | tar -x
xz‘nin kendi -T parametresi de çok iş görüyor, ama pixz özellikle tar işlemlerinde daha entegre bir deneyim sunuyor.
Log Arşivleme: Pratik Senaryo
Sysadmin olarak en sık yaptığım işlerden biri log arşivleme. Şöyle bir senaryoyu ele alalım: Nginx access logları her gün onlarca GB büyüyor ve bunları 90 günlüğüne tutmak zorundayız.
#!/bin/bash
# log_arsivle.sh
# Logrotate'in ardından çalışacak şekilde ayarlanmış
LOG_DIZIN="/var/log/nginx"
ARSIV_DIZIN="/mnt/arsiv/nginx_logs"
TARIH=$(date +%Y%m)
mkdir -p "${ARSIV_DIZIN}/${TARIH}"
# Dünün rotate edilmiş loglarını bul ve sıkıştır
find "$LOG_DIZIN" -name "*.log.1" | while read log_dosyasi; do
temel_ad=$(basename "$log_dosyasi" .log.1)
hedef="${ARSIV_DIZIN}/${TARIH}/${temel_ad}_$(date +%Y%m%d).log"
# Dosyayı arşive kopyala
cp "$log_dosyasi" "$hedef"
# xz ile sıkıştır
xz -6 -T 2 "$hedef"
echo "Arşivlendi: ${hedef}.xz"
done
# 90 günden eski arşivleri temizle
find "$ARSIV_DIZIN" -name "*.xz" -mtime +90 -delete
echo "Log arşivleme tamamlandı."
Bu scriptte -T 2 kullanıyorum çünkü bu sunucuda aynı anda başka işler de çalışıyor. Tüm CPU’yu log sıkıştırmaya vermek istemiyorum.
Dosya Bütünlüğü Kontrolü
Uzun süreli arşivlerde dosya bozulması ciddi bir risk. bzip2 ve xz bu konuda yerleşik test mekanizmaları sunuyor:
# bzip2 bütünlük testi
bzip2 -t yedek.tar.bz2
echo "Çıkış kodu: $?" # 0 ise dosya sağlam
# xz bütünlük testi
xz -t yedek.tar.xz
echo "Çıkış kodu: $?"
# Toplu test
for f in /arsiv/*.xz; do
if xz -t "$f" 2>/dev/null; then
echo "OK: $f"
else
echo "HATA: $f - Dosya bozuk!" >&2
fi
done
Bu testi, önemli arşivler için cron’a ekleyip sonuçları mail ile izliyorum. Bir yedek bozuksa, gerektiğinde bunu öğrenmek için o anı beklemek istemezsin.
Hangi Durumda Hangisini Kullanmalısın?
bzip2 kullan:
- Legacy sistemlerle uyumluluk gerektiğinde
- Python, Perl gibi dillerde yerleşik bzip2 desteğinden yararlanmak istediğinde
- Orta düzey sıkıştırma yeterli olduğunda ve işlem süresi kritik değilse
pbzip2ile paralel işlem yapacaksan ve xz kurulu değilse
xz kullan:
- Maksimum sıkıştırma oranı öncelikliyse
- Uzun süreli arşivler oluşturuyorsan
- Dosyayı çok kez aktaracaksan ve bant genişliği değerliyse
- Modern sistemlerle çalışıyorsan ve uyumluluk sorunu yoksa
- Kernel, büyük yazılım arşivleri gibi dağıtım amacıyla paketleme yapıyorsan
gzip’i tercih et:
- Hız öncelikliyse
- Sık erişilen, sık değişen verilerle çalışıyorsan
- Web sunucu sıkıştırması gibi gerçek zamanlı uygulamalarda
- Streaming pipeline’larda gecikme istemiyorsan
Sıkıştırma Seviyesi Optimizasyonu
Her zaman maksimum seviye gerekmiyor. Özellikle xz -9 gereksiz kaynak tüketimine neden olabiliyor. Kendi deneyimimden bir kural:
# Günlük rotasyon, hız önemli
xz -3 -T 4 günlük_log.txt
# Haftalık arşiv, denge
xz -6 -T 4 haftalık_arşiv.tar
# Yıllık soğuk arşiv, maksimum sıkıştırma
xz -9 -e -T 8 yillik_arsiv.tar
-e (extreme) parametresi sıkıştırma seviyesini değiştirmez, ama aynı seviyede biraz daha fazla çaba harcayarak genellikle %5-10 daha iyi sonuç verir. Soğuk arşivler için buna değer.
Çok Parçalı Arşivler ve split Kombinasyonu
Büyük arşivleri belirli boyutlarda parçalara bölmek bazen gerekiyor. Örneğin FAT32 formatlı bir diskin 4 GB dosya sınırı varsa ya da bir yükleme sistemi 2 GB’dan büyük dosyaları reddediyorsa:
# Önce tar, sonra xz, sonra split
tar -c /büyük/veri | xz -6 -T 4 | split -b 2G - yedek_parcalar.tar.xz.
# Parçaları birleştirip açmak
cat yedek_parcalar.tar.xz.* | xz -d | tar -x
# Parça boyutunu ihtiyaca göre ayarla
tar -c /büyük/veri | bzip2 -9 | split -b 4G - yedek.tar.bz2.
Bu yöntem özellikle bulut depolama servislerine multipart upload yaparken ya da fiziksel medyaya kopyalarken çok işe yarıyor.
Performans İzleme
Büyük sıkıştırma işlemleri sırasında ne olduğunu izlemek için:
# xz ilerleme durumunu göster
xz -v -6 büyük_dosya.tar
# Arka planda çalışan xz işlemini izle
watch -n 1 'ls -lh *.xz && ps aux | grep xz'
# pv ile ilerleme çubuğu ekle
tar -c /veri | pv | xz -6 -T 4 > arşiv.tar.xz
# pv ile boyut bilgisi de ver
tar -c /veri | pv -s $(du -sb /veri | cut -f1) | xz -6 -T 4 > arşiv.tar.xz
pv (pipe viewer) gerçekten hayat kurtaran bir araç. “Bu komut hâlâ çalışıyor mu yoksa dondu mu?” sorusunu ortadan kaldırıyor.
Sonuç
bzip2 ve xz, sysadmin araç kutusunun vazgeçilmez parçaları. Her ikisi de “çabuk lazım” senaryoları için değil, “doğru yapılmış” senaryolar için var. Veritabanı yedekleri, log arşivleri, yazılım dağıtım paketleri, uzun vadeli soğuk depolama… bu alanlarda gzip‘in sunduğu sıkıştırma oranı çoğu zaman yetersiz kalıyor.
Günümüzde genel önerim şu yönde: Yeni kurulum yapıyorsan ve uyumluluk sorunu yoksa direkt xz‘ye geç. Hem oranı daha iyi, hem araç seti daha modern, hem de çoklu thread desteği daha olgun. bzip2‘ye ise eski sistemler veya mevcut .bz2 arşivlerle çalışmak zorunda kaldığında dönüyorum.
En önemli nokta şu: Hangi aracı seçersen seç, sıkıştırılmış dosyalarını düzenli olarak test et. xz -t ya da bzip2 -t komutu birkaç saniyeni alır, ama o yedeklere gerçekten ihtiyaç duyduğun an seni pişmanlıktan kurtarır. Bunu bir cron job’a eklemek, sabah uyandığında iyi bir kahve içmek kadar tatmin edici.