tar ile Belirli Dosya Tiplerini Seçerek Arşivleme

Dosya sunucusunu temizlerken “şu log dosyalarını arşivlesem de sileceğim ama önce yedekleyeyim” dediğiniz oldu mu hiç? Ya da bir projeyi teslim ederken sadece .py dosyalarını, sadece konfigürasyon dosyalarını veya sadece belirli bir uzantıyı arşivlemek istediniz? İşte tam bu noktada tar komutunun esnekliği devreye giriyor. Çoğu sysadmin tar komutunu basit bir “hepsini al, sıkıştır, gönder” aracı olarak kullanır. Oysa tar, belirli dosya tiplerini, desenleri ve kriterleri hedef alarak son derece akıllı arşivler oluşturabilen güçlü bir araçtır.

tar Komutuna Hızlı Bakış

tar (Tape ARchive) onlarca yıldır Unix/Linux dünyasının vazgeçilmez arşivleme aracıdır. Temel kullanımını zaten biliyorsunuzdur ama belirli dosya tiplerini seçerek arşivleme söz konusu olduğunda birkaç farklı yaklaşım mevcuttur.

Sık kullanacağımız tar parametrelerine hızlıca göz atalım:

  • -c: Yeni arşiv oluştur (create)
  • -v: Ayrıntılı çıktı ver (verbose)
  • -f: Arşiv dosyasının adını belirt (file)
  • -z: gzip sıkıştırması kullan
  • -j: bzip2 sıkıştırması kullan
  • -J: xz sıkıştırması kullan
  • –exclude: Belirli dosya veya desenleri dışla
  • -T: Arşivlenecek dosyaların listesini bir dosyadan oku
  • –include: Belirli desenleri dahil et (newer tar versiyonlarında)

Temel Yaklaşım: Glob ile Dosya Uzantısı Belirtmek

En basit yöntem doğrudan glob deseni kullanmaktır. Bir dizindeki tüm .log dosyalarını arşivlemek istiyorsanız:

tar -czvf log_arsivi.tar.gz /var/log/*.log

Ancak bu yaklaşımın önemli bir sınırı var: alt dizinleri kapsamaz. /var/log altındaki tüm alt klasörlerdeki .log dosyalarına ulaşmak için bu yeterli değildir. Şimdi daha güçlü yöntemlere geçelim.

find ile Kombinasyon: Gerçek Güç Burada

find komutunu tar ile birleştirmek, belirli dosya tiplerini seçerek arşivlemenin en esnek ve güvenilir yoludur. Bu ikilinin gücünü birkaç farklı senaryoyla inceleyelim.

Senaryo 1: Tüm Alt Dizinlerdeki Log Dosyalarını Arşivleme

Bir uygulama sunucusunda birden fazla servisin log dosyaları farklı dizinlere dağılmış durumda. Hepsini tek bir arşivde toplamak istiyorsunuz:

find /var/log -name "*.log" -print0 | tar -czvf /backup/logs_$(date +%Y%m%d).tar.gz --null -T -

Burada birkaç önemli nokta var:

  • -print0: Dosya adlarını null karakter ile ayırır, böylece boşluk içeren dosya adlarında sorun yaşanmaz
  • –null: tar‘a, dosya listesinin null karakterle ayrıldığını söyler
  • -T –: Standart girdiden dosya listesini oku

Bu yöntem production ortamında güvenle kullanabileceğiniz, sağlam bir yaklaşımdır.

Senaryo 2: Belirli Bir Yaştan Eski Log Dosyalarını Arşivleme

Disk dolmadan önce önlem almak istiyorsunuz. 30 günden eski log dosyalarını arşivleyip temizlemek için:

find /var/log/nginx -name "*.log" -mtime +30 -print0 | 
  tar -czvf /backup/old_nginx_logs_$(date +%Y%m%d).tar.gz --null -T -

Arşivleme başarılı olduktan sonra silmek için:

find /var/log/nginx -name "*.log" -mtime +30 -exec rm {} ;

Tabii silinmeden önce arşivin doğrulanması iyi bir pratiktir:

tar -tzvf /backup/old_nginx_logs_$(date +%Y%m%d).tar.gz | head -20

Senaryo 3: Birden Fazla Uzantıyı Aynı Anda Arşivleme

Bir web projesi dizininde sadece konfigürasyon ve script dosyalarını arşivlemek istiyorsunuz:

find /opt/webapp -type f ( -name "*.conf" -o -name "*.cfg" -o -name "*.sh" ) -print0 | 
  tar -czvf /backup/webapp_configs_$(date +%Y%m%d).tar.gz --null -T -

Parantez içindeki -o operatörü “veya” anlamına gelir. Bu şekilde birden fazla uzantıyı tek komutla hedefleyebilirsiniz.

–exclude ile Belirli Tipleri Dışlayarak Arşivleme

Bazen “şunlar hariç her şey” yaklaşımı daha pratik olabilir. Özellikle büyük bir dizini arşivlerken gereksiz dosyaları dışlamak istediğinizde --exclude parametresi işinizi görür.

tar -czvf proje_arsivi.tar.gz /opt/myproject 
  --exclude="*.log" 
  --exclude="*.tmp" 
  --exclude="*.cache" 
  --exclude="node_modules" 
  --exclude=".git"

Bu komut /opt/myproject dizinini arşivler ancak log dosyaları, geçici dosyalar, cache dosyaları, node_modules klasörü ve git dizinini dışarıda bırakır. Yazılım geliştiricilerin kod yedeklerken sık kullandığı bir pattern’dir bu.

–exclude-from ile Dışlama Listesi Dosyası Kullanmak

Dışlanacak dosya tipleri çok fazlaysa, bunları bir dosyaya yazıp --exclude-from ile kullanabilirsiniz:

cat > /tmp/exclude_list.txt << EOF
*.log
*.tmp
*.cache
*.pyc
__pycache__
node_modules
.git
.DS_Store
Thumbs.db
EOF

tar -czvf /backup/proje_$(date +%Y%m%d).tar.gz /opt/myproject 
  --exclude-from=/tmp/exclude_list.txt

Bu yaklaşım özellikle CI/CD pipeline’larında veya cron job’larında tutarlılık sağlar. Dışlama listesini bir kez yazarsınız, her seferinde aynı listeyi kullanırsınız.

-T Parametresi ile Dosya Listesinden Arşivleme

Arşivlenecek dosyaları önceden bir listeye yazıp bu listeden arşiv oluşturabilirsiniz. Bu yöntem özellikle karmaşık seçim kriterleriniz olduğunda veya arşivlemeden önce listeyi incelemek istediğinizde kullanışlıdır.

# Önce listeyi oluştur ve kontrol et
find /home -name "*.sql" -o -name "*.dump" > /tmp/db_dosyalari.txt
cat /tmp/db_dosyalari.txt

# Listeyi onayladıktan sonra arşivle
tar -czvf /backup/veritabani_yedek_$(date +%Y%m%d).tar.gz -T /tmp/db_dosyalari.txt

Bu iki adımlı yaklaşım, özellikle production ortamında yanlış dosyaları arşivleme riskini azaltır. Listeyi önce gözden geçirirsiniz, sonra arşivlemeyi çalıştırırsınız.

Gerçek Dünya Senaryoları

Senaryo: Geliştirme Ortamında Python Proje Yedekleme

Bir Django projesini yedekliyorsunuz. Sadece kaynak kodunu istiyorsunuz, compiled dosyaları, virtual environment’ı ve cache dosyalarını istemiyorsunuz:

#!/bin/bash
PROJE_DIZIN="/home/developer/django_projesi"
YEDEK_DIZIN="/backup/kod_yedekleri"
TARIH=$(date +%Y%m%d_%H%M%S)

find "$PROJE_DIZIN" -type f ( 
  -name "*.py" -o 
  -name "*.html" -o 
  -name "*.css" -o 
  -name "*.js" -o 
  -name "*.json" -o 
  -name "*.txt" -o 
  -name "*.md" 
) 
  ! -path "*/node_modules/*" 
  ! -path "*/.git/*" 
  ! -path "*/__pycache__/*" 
  ! -path "*/venv/*" 
  ! -path "*/.venv/*" 
  -print0 | tar -czvf "$YEDEK_DIZIN/django_kaynak_$TARIH.tar.gz" --null -T -

echo "Arşiv oluşturuldu: $YEDEK_DIZIN/django_kaynak_$TARIH.tar.gz"
echo "Boyut: $(du -sh $YEDEK_DIZIN/django_kaynak_$TARIH.tar.gz | cut -f1)"

Burada ! -path ile belirli dizinleri tamamen dışladık. Bu, --exclude‘dan farklı olarak find seviyesinde filtreleme yapıyor.

Senaryo: Sunucu Konfigürasyon Dosyalarını Yedekleme

Bir Linux sunucusundaki tüm servis konfigürasyon dosyalarını arşivlemek istiyorsunuz. Bu işlemi her hafta otomatik yapan bir script:

#!/bin/bash
YEDEK_DIZIN="/backup/konfig_yedekleri"
TARIH=$(date +%Y%m%d)
ARSIV_ADI="$YEDEK_DIZIN/server_konfig_$TARIH.tar.gz"

# /etc dizininden konfigürasyon dosyalarını topla
find /etc -type f ( 
  -name "*.conf" -o 
  -name "*.cfg" -o 
  -name "*.ini" -o 
  -name "*.yaml" -o 
  -name "*.yml" 
) -print0 | tar -czvf "$ARSIV_ADI" --null -T -

# Arşiv doğrulama
if tar -tzf "$ARSIV_ADI" > /dev/null 2>&1; then
    echo "$(date): Konfigürasyon yedeği başarılı - $ARSIV_ADI" >> /var/log/yedek.log
else
    echo "$(date): HATA - Arşiv doğrulanamadı!" >> /var/log/yedek.log
    exit 1
fi

# 30 günden eski yedekleri sil
find "$YEDEK_DIZIN" -name "server_konfig_*.tar.gz" -mtime +30 -delete

Senaryo: Medya Dosyalarını Türlerine Göre Ayrı Arşivleme

Büyük bir medya dizinini dosya türlerine göre ayrı arşivlere bölmek istiyorsunuz:

#!/bin/bash
KAYNAK="/data/medya"
HEDEF="/backup/medya"
TARIH=$(date +%Y%m%d)

# Görsel dosyalar
find "$KAYNAK" -type f ( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" ) 
  -print0 | tar -czvf "$HEDEF/gorseller_$TARIH.tar.gz" --null -T -

# Video dosyalar
find "$KAYNAK" -type f ( -iname "*.mp4" -o -iname "*.avi" -o -iname "*.mkv" ) 
  -print0 | tar -cjvf "$HEDEF/videolar_$TARIH.tar.bz2" --null -T -

# Döküman dosyalar
find "$KAYNAK" -type f ( -iname "*.pdf" -o -iname "*.doc" -o -iname "*.docx" -o -iname "*.xlsx" ) 
  -print0 | tar -czvf "$HEDEF/dokumanlar_$TARIH.tar.gz" --null -T -

echo "Medya arşivleme tamamlandı."

Dikkat ettiyseniz -iname kullandım. Bu büyük/küçük harf duyarsız eşleşme sağlar. .JPG de .jpg de yakalanır.

Arşiv Doğrulama ve İçerik Listeleme

Arşiv oluşturduktan sonra içeriğini doğrulamak iyi bir alışkanlıktır:

# Arşiv içeriğini listele
tar -tzvf arsiv.tar.gz

# Sadece belirli uzantılı dosyaları listele
tar -tzvf arsiv.tar.gz | grep ".log$"

# Arşiv bütünlüğünü test et (extract etmeden)
tar -tzf arsiv.tar.gz > /dev/null && echo "Arşiv geçerli" || echo "Arşiv bozuk!"

# Dosya sayısını öğren
tar -tzf arsiv.tar.gz | grep -v "/$" | wc -l

Sıkıştırma Seçenekleri: Hangisini Kullanmalı?

Dosya tipine göre sıkıştırma algoritması seçimi önemlidir:

  • -z (gzip): Hızlı sıkıştırma/açma, orta sıkıştırma oranı. Log dosyaları için ideal. .tar.gz
  • -j (bzip2): Daha iyi sıkıştırma, daha yavaş. Metin ağırlıklı arşivler için uygun. .tar.bz2
  • -J (xz): En iyi sıkıştırma oranı, en yavaş. Uzun süre saklanacak arşivler için. .tar.xz
  • Sıkıştırmasız: Zaten sıkıştırılmış dosyalar (jpg, mp4, zip) için -z kullanmaya gerek yok. .tar

Görsel ve video dosyaları zaten sıkıştırılmış olduğundan gzip ile çok az kazanç elde edersiniz, dahası işlem süresi uzar. Bu dosyalar için düz .tar veya hafif sıkıştırma kullanın.

Dikkat Edilmesi Gereken Noktalar

Mutlak vs. Göreli Yol Sorunu

tar varsayılan olarak mutlak yolları başındaki / işareti olmadan saklar. Arşivden çıkarırken dikkatli olun:

# Arşivdeki yolları gör
tar -tzf arsiv.tar.gz | head -5

# Mutlak yolu korumak istiyorsanız (nadiren önerilir)
tar -czvf arsiv.tar.gz -P /etc/nginx/

# Arşivi belirli bir dizine çıkarmak
tar -xzvf arsiv.tar.gz -C /tmp/geri_yukle/

Büyük Arşivlerde Performans

Çok sayıda küçük dosyayı arşivlerken find çıktısını önce dosyaya yazıp sonra kullanmak daha iyi performans verebilir:

find /var/log -name "*.log" -print0 > /tmp/log_listesi.txt
tar -czvf /backup/logs.tar.gz --null -T /tmp/log_listesi.txt
rm /tmp/log_listesi.txt

Sembolik Linklere Dikkat

find varsayılan olarak sembolik linkleri takip etmez. Sembolik linkin hedefini arşivlemek istiyorsanız:

find /etc -L -name "*.conf" -print0 | tar -czvf konfig.tar.gz --null -T -

-L parametresi find‘a sembolik linkleri takip etmesini söyler.

İlerlemeyî Takip Etmek

Büyük arşivlerde işlemin ne kadar sürdüğünü görmek istersiniz. pv (pipe viewer) aracı varsa:

find /data -name "*.log" -print0 | 
  tar -czvf - --null -T - | 
  pv > /backup/buyuk_arsiv.tar.gz

pv yoksa basitçe v (verbose) parametresi ile hangi dosyaların eklendiğini canlı izleyebilirsiniz. Çok fazla dosya varsa bunu bir log dosyasına yönlendirin:

find /var/log -name "*.log" -print0 | 
  tar -czvf /backup/logs.tar.gz --null -T - 2>&1 | 
  tee /tmp/arsivleme_log.txt

Sonuç

tar komutunu sadece “bir dizini sıkıştır” aracı olarak kullanmak, bu güçlü aracın kapasitesinin çok küçük bir kısmını kullanmak demektir. find ile kombinasyon, --exclude ve --exclude-from parametreleri, -T ile dosya listesi okuma gibi yöntemler bir araya geldiğinde son derece hassas ve akıllı arşivleme işlemleri yapabilirsiniz.

Günlük sysadmin hayatında en çok işe yarayan kombinasyon genellikle find ... -print0 | tar ... --null -T - şeklindedir. Bu yöntem boşluk içeren dosya adlarını, sembolik linkleri ve karmaşık filtreleme koşullarını doğru biçimde ele alır.

Arşivleme script’lerinizi yazarken şu üç şeyi unutmayın: arşiv oluşturduktan sonra mutlaka doğrulayın, eski arşivleri temizleyecek bir mekanizma kurun ve script’lerinizi log’layın. Bir gün “bu arşivi ne zaman ve nasıl oluşturduk?” sorusunu yanıtlamak zorunda kalacaksınız, iyi bir log o anda hayat kurtarır.

Yorum yapın