Rsync Filtreler ile Seçici Yedekleme
Yedekleme işlemlerinde en çok yapılan hatalardan biri, her şeyi körü körüne yedeklemek. Geliştirme ortamındaki node_modules klasörünü, log dosyalarını, geçici dosyaları da yedekliyorsunuz ve sonunda depolama alanınız dolup taşıyor, yedekleme süreniz saatlere uzuyor. Rsync’in filtre sistemi tam da bu sorunu çözmek için var. Doğru yapılandırıldığında, sadece gerçekten ihtiyacınız olan dosyaları yedeklersiniz, hem zaman kazanırsınız hem de disk kullanımını dramatik biçimde azaltırsınız.
Rsync Filtre Sistemi Nasıl Çalışır?
Rsync’in filtre mekanizması, dosyaları include (dahil et) ve exclude (hariç tut) kurallarıyla kontrol etmenizi sağlar. Burada dikkat edilmesi gereken en kritik nokta: rsync kuralları sırayla işler ve ilk eşleşen kuralı uygular. Yani kural sırası son derece önemlidir.
Üç temel yöntem var:
--includeve--excludeparametreleri komut satırında doğrudan kullanmak--filterparametresiyle gelişmiş kural tanımlamak--exclude-fromveya--filterile harici dosyadan kural okumak
Basit bir örnekle başlayalım. Bir dizindeki sadece .conf dosyalarını yedeklemek istiyorsunuz:
rsync -av --include="*.conf" --exclude="*" /etc/ /backup/etc/
Burada sıralama çok önemli. Önce .conf dosyalarını dahil et, sonra geri kalanların hepsini hariç tut diyoruz. Sıralamayı tersine çevirirseniz, --exclude="*" her şeyi hemen bloke eder ve --include hiç çalışmaz.
Temel Include/Exclude Sözdizimi
Wildcard karakterlerini anlamak, etkili filtreler yazmanın temelidir.
*: Tek dizin seviyesinde her karakterle eşleşir (slash hariç)**: Birden fazla dizin seviyesini de kapsar?: Tek bir karakterle eşleşir[abc]: Belirtilen karakterlerden biriyle eşleşir
Dizinleri hariç tutmak için sona / eklemek en temiz yöntemdir:
rsync -av
--exclude="node_modules/"
--exclude=".git/"
--exclude="__pycache__/"
--exclude="*.pyc"
--exclude="*.log"
--exclude="tmp/"
/home/deploy/apps/ /backup/apps/
Bu örnekte node_modules/ sonundaki slash, rsync’e bunun bir dizin olduğunu söyler. Slash olmadan, aynı isimde bir dosya varsa o da hariç tutulur. Çoğu durumda bu fark önemli olmasa da, kesinlik için slash kullanmak iyi bir alışkanlıktır.
Filtre Dosyaları ile Çalışmak
Komut satırına çok sayıda filtre yazmak hem okunaksız hem de yönetilmesi zor hale gelir. Bunun yerine bir filtre dosyası kullanabilirsiniz.
/etc/rsync-filters/web-backup.filter dosyası oluşturalım:
# Web uygulama yedekleme filtre dosyası
# Syntax: + include, - exclude
# Önce dahil edilecekler
+ /public/
+ /public/**
+ /src/
+ /src/**
+ /config/
+ /config/*.conf
+ /config/*.env.example
# Büyük ve gereksiz dizinler
- node_modules/
- vendor/
- .git/
- .svn/
# Geçici ve önbellek dosyaları
- *.cache
- *.tmp
- /tmp/
- /cache/
- __pycache__/
- *.pyc
- *.pyo
# Log dosyaları (bunları ayrı işleyelim)
- *.log
- /logs/
# Build çıktıları
- /dist/
- /build/
- /.next/
- /.nuxt/
# IDE ve editor dosyaları
- .idea/
- .vscode/
- *.swp
- *~
Bu dosyayı kullanmak için:
rsync -av --filter="merge /etc/rsync-filters/web-backup.filter"
/var/www/html/ user@backup-server:/backup/web/
merge keyword’ü, belirtilen dosyadaki kuralları mevcut filtre listesine dahil eder. dir-merge ise her dizinde özel filtre dosyaları aramanızı sağlar, bunu birazdan göreceğiz.
Gerçek Dünya Senaryosu: Geliştirici Workstation Yedeklemesi
Bir geliştirici workstation’ını yedekliyorsunuz. Bu makinede Python, Node.js ve Go projeleri var. Her birinin kendi gereksiz dosyaları mevcut.
/etc/rsync-filters/dev-workstation.filter:
# ============================================
# Geliştirici Workstation Filtre Kuralları
# ============================================
# HOME dizini özel klasörleri dahil et
+ /home/
+ /home/*/
+ /home/*/projects/
+ /home/*/documents/
+ /home/*/dotfiles/
# Konfigürasyon dosyaları
+ /home/*/.bashrc
+ /home/*/.zshrc
+ /home/*/.gitconfig
+ /home/*/.ssh/
+ /home/*/.ssh/config
+ /home/*/.ssh/authorized_keys
# SSH private key'lerini yedekle ama dikkatli şifrele
+ /home/*/.ssh/id_*
# Node.js projeleri - node_modules hariç
- /home/*/projects/**/node_modules/
- /home/*/projects/**/.next/
- /home/*/projects/**/.nuxt/
- /home/*/projects/**/dist/
# Python projeleri
- /home/*/projects/**/__pycache__/
- /home/*/projects/**/*.pyc
- /home/*/projects/**/.venv/
- /home/*/projects/**/venv/
- /home/*/.cache/pip/
# Go projeleri
- /home/*/go/pkg/
- /home/*/projects/**/vendor/
# Genel cache ve geçici dosyalar
- /home/*/.cache/
- /home/*/.local/share/Trash/
- /home/*/.mozilla/firefox/*/Cache/
- /home/*/.config/google-chrome/Default/Cache/
- /home/*/Downloads/
# Büyük medya dosyaları (opsiyonel)
- *.iso
- *.vmdk
- *.ova
# Geri kalan her şeyi dahil et
+ *
Bu filtreyi kullanan yedekleme scripti:
#!/bin/bash
# dev-workstation-backup.sh
BACKUP_SOURCE="/"
BACKUP_DEST="backup@nas-server:/backups/workstations/$(hostname)"
FILTER_FILE="/etc/rsync-filters/dev-workstation.filter"
LOG_FILE="/var/log/rsync-backup.log"
DATE=$(date +%Y-%m-%d_%H-%M)
echo "[$DATE] Yedekleme başlıyor..." >> "$LOG_FILE"
rsync -avz
--filter="merge $FILTER_FILE"
--delete
--delete-excluded
--stats
--human-readable
--log-file="$LOG_FILE"
--timeout=120
"$BACKUP_SOURCE" "$BACKUP_DEST"
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "[$DATE] Yedekleme başarıyla tamamlandı." >> "$LOG_FILE"
else
echo "[$DATE] HATA: Yedekleme başarısız oldu. Çıkış kodu: $EXIT_CODE" >> "$LOG_FILE"
# Burada bir bildirim sistemi tetikleyebilirsiniz
fi
--delete-excluded parametresine dikkat edin. Bu parametre, hedefte olan ama artık hariç tutulmuş dosyaları siler. Eğer bir gün node_modules klasörünü filtrelerinize eklerseniz ve daha önce yedeklenmiş bu klasörü hedeften de silmek istiyorsanız bu parametre işinize yarar. Ancak dikkatli kullanın.
Dir-Merge ile Proje Bazlı Filtreler
dir-merge özelliği çok güçlü ama az bilinen bir özelliktir. Her dizine özel bir .rsync-filter dosyası koyabilir ve rsync bu dosyaları otomatik olarak bulup uygular.
Örneğin, büyük bir monorepo yapınız var ve her alt projenin kendi yedekleme kuralları olsun istiyorsunuz:
rsync -av
--filter="dir-merge /.rsync-filter"
/var/www/projects/ user@backup:/backup/projects/
/var/www/projects/frontend-app/.rsync-filter dosyası:
- node_modules/
- .next/
- .cache/
- coverage/
- *.test.js.snap
/var/www/projects/backend-api/.rsync-filter dosyası:
- vendor/
- storage/logs/*.log
- bootstrap/cache/
- .env
+ .env.example
Bu yöntemle her proje kendi kurallarını taşır ve merkezi bir filtre dosyasını güncellemenize gerek kalmaz. Özellikle farklı ekiplerin farklı projeleri yönettiği ortamlarda çok pratiktir.
Filtrelerinizi Test Etmek: –dry-run ve –list-only
Filtre yazmak bazen beklenmedik sonuçlar doğurabilir. Önemli bir dosyanın yanlışlıkla hariç tutulması felakete yol açabilir. Bu yüzden her zaman test edin.
--dry-run veya -n parametresi gerçekte hiçbir şey kopyalamaz, sadece ne yapılacağını gösterir:
rsync -avn --filter="merge /etc/rsync-filters/web-backup.filter"
/var/www/html/ user@backup-server:/backup/web/
Hangi dosyaların hariç tutulduğunu görmek için özel bir numara var. Rsync normalde hariç tutulan dosyaları göstermez. Görmek için --debug=FILTER kullanabilirsiniz:
rsync -av --debug=FILTER
--filter="merge /etc/rsync-filters/web-backup.filter"
/var/www/html/ /tmp/test-backup/ 2>&1 | head -50
Ya da daha okunabilir bir yöntem olarak, sadece hariç tutulanları listelemek için:
rsync -av --dry-run
--filter="merge /etc/rsync-filters/web-backup.filter"
/var/www/html/ /tmp/test-backup/
| grep "^skipping"
Ayrıca --itemize-changes parametresi her dosya için ne yapıldığını ayrıntılı gösterir:
rsync -av --itemize-changes --dry-run
--exclude="*.log"
--exclude="tmp/"
/var/www/ /tmp/test/
| grep "^>" | head -20
Seçici Artımlı Yedekleme: Boyut ve Zaman Filtreleri
Rsync, filtreler dışında dosyaları boyutlarına veya değiştirilme tarihlerine göre de kısıtlamanıza izin verir.
–max-size: Belirtilen boyuttan büyük dosyaları atla –min-size: Belirtilen boyuttan küçük dosyaları atla –max-age: Belirtilen günden daha eski dosyaları atla –min-age: Belirtilen günden daha yeni dosyaları atla
Örneğin, log dosyalarını yedeklerken sadece son 7 günün loglarını almak istiyorsunuz ve 100MB’dan büyük dosyaları atlamak istiyorsunuz:
rsync -av
--include="*.log"
--exclude="*"
--max-size=100m
--min-age=1
--max-age=7
/var/log/ backup@logserver:/backup/logs/$(date +%Y-%m)/
Bu parametre kombinasyonunu bir cron job ile kullanarak otomatik hale getirebilirsiniz:
# /etc/cron.d/selective-backup
# Her gece 02:30'da çalışır
30 2 * * * root /usr/local/bin/selective-backup.sh >> /var/log/backup-cron.log 2>&1
# Her pazartesi 03:00'da haftalık yedekleme
0 3 * * 1 root /usr/local/bin/weekly-backup.sh >> /var/log/backup-cron.log 2>&1
Gelişmiş Senaryo: Çok Katmanlı Filtre Stratejisi
Büyük bir sunucu parkını yöneten bir sysadmin olarak, farklı sunucu türleri için farklı yedekleme stratejileriniz olması gerekir. İşte gerçek hayatta kullandığım bir yaklaşım:
#!/bin/bash
# advanced-backup.sh
# Sunucu tipine göre farklı filtre stratejileri uygular
SERVER_TYPE="${1:-generic}" # web, db, mail, generic
BACKUP_DEST="backup@central-backup:/backups/$(hostname)"
BASE_FILTER="/etc/rsync-filters"
# Ortak temel filtreler
COMMON_EXCLUDES=(
"--exclude=*.tmp"
"--exclude=*.swp"
"--exclude=*.bak"
"--exclude=/proc/"
"--exclude=/sys/"
"--exclude=/dev/"
"--exclude=/run/"
"--exclude=/media/"
"--exclude=/mnt/"
"--exclude=/tmp/"
"--exclude=/var/tmp/"
)
case "$SERVER_TYPE" in
web)
FILTER_FILE="$BASE_FILTER/web-server.filter"
EXTRA_EXCLUDES=(
"--exclude=/var/www/*/node_modules/"
"--exclude=/var/www/*/.git/"
"--exclude=/var/www/*/vendor/"
)
;;
db)
FILTER_FILE="$BASE_FILTER/db-server.filter"
EXTRA_EXCLUDES=(
"--exclude=/var/lib/mysql/ib_logfile*"
"--exclude=/var/lib/postgresql/*/pg_wal/"
)
;;
mail)
FILTER_FILE="$BASE_FILTER/mail-server.filter"
EXTRA_EXCLUDES=(
"--exclude=/var/spool/postfix/active/"
"--exclude=/var/spool/postfix/incoming/"
)
;;
*)
FILTER_FILE="$BASE_FILTER/generic-server.filter"
EXTRA_EXCLUDES=()
;;
esac
echo "Sunucu tipi: $SERVER_TYPE"
echo "Filtre dosyası: $FILTER_FILE"
echo "Yedekleme başlıyor..."
rsync -avz
--filter="merge $FILTER_FILE"
"${COMMON_EXCLUDES[@]}"
"${EXTRA_EXCLUDES[@]}"
--delete
--stats
--human-readable
--one-file-system
/ "$BACKUP_DEST"
echo "Tamamlandı. Çıkış kodu: $?"
Kullanımı:
./advanced-backup.sh web
./advanced-backup.sh db
./advanced-backup.sh mail
--one-file-system parametresi mount point sınırlarını aşmaz, yani /proc gibi sanal dosya sistemlerine girme riskini azaltır.
Sık Yapılan Hatalar ve Çözümleri
Hata 1: Include/Exclude sırasını karıştırmak
# YANLIŞ - Bu hiçbir şeyi yedeklemez!
rsync -av --exclude="*" --include="*.conf" /etc/ /backup/etc/
# DOĞRU
rsync -av --include="*.conf" --exclude="*" /etc/ /backup/etc/
Hata 2: Üst dizini include etmemek
Alt dizindeki dosyaları dahil etmek istiyorsanız, üst dizini de açıkça dahil etmelisiniz:
# YANLIŞ - config/ içindeki .conf dosyaları yedeklenmez
rsync -av
--include="config/*.conf"
--exclude="*"
/var/www/ /backup/
# DOĞRU - Önce dizini, sonra içeriği dahil et
rsync -av
--include="config/"
--include="config/*.conf"
--exclude="*"
/var/www/ /backup/
Hata 3: ve farkını anlamamak*
# Sadece bir seviye derinlikte çalışır
--exclude="*/node_modules"
# Tüm alt dizinlerdeki node_modules'leri yakalar
--exclude="**/node_modules"
Filtre Yönetimi için İpuçları
Zaman içinde filtre dosyaları karmaşık hale gelebilir. Birkaç pratik öneri:
- Filtre dosyalarını versiyon kontrolüne (git) alın
- Her kural için yorum satırı ekleyin, gelecekteki sizi teşekkür eder
rsync --versionile versiyonu kontrol edin, eski sürümlerde bazı özellikler olmayabilir- Büyük filtre dosyalarını kategorilere ayırın ve
mergeile birleştirin - Düzenli aralıklarla
--dry-runile filtreleri doğrulayın - Kritik dosyaların yedeklendiğini periyodik olarak test edin, sadece sürecin çalıştığını değil
# Filtre dosyasını test eden basit bir doğrulama scripti
#!/bin/bash
CRITICAL_FILES=(
"/etc/passwd"
"/etc/ssh/sshd_config"
"/var/www/html/index.php"
)
for file in "${CRITICAL_FILES[@]}"; do
if rsync -n --filter="merge /etc/rsync-filters/main.filter"
"$file" /dev/null 2>&1 | grep -q "skipping"; then
echo "UYARI: Kritik dosya yedeklenmiyor: $file"
else
echo "OK: $file yedeklenecek"
fi
done
Sonuç
Rsync’in filtre sistemi başlangıçta karmaşık görünebilir ama bir kez alıştıktan sonra yedekleme işlemlerinizi kökten dönüştürür. Gereksiz dosyaları hariç tutarak hem depolama maliyetinizi düşürürsünüz hem de yedekleme sürelerinizi kısaltırsınız. Benim deneyimimde, iyi yazılmış filtrelerle tipik bir geliştirici workstation yedeklemesi %60-70 daha az veri transfer eder.
En önemli prensipleri bir kez daha vurgulayayım: Kural sırası her şeydir, include her zaman exclude’dan önce gelir, üst dizinleri dahil etmeyi unutmayın ve her değişiklikten sonra --dry-run ile test edin. Filtre dosyalarınızı git’e koyun, iyi yorum yazın ve kritik dosyaların gerçekten yedeklendiğini periyodik olarak doğrulayın.
Yedekleme işlemi sadece bir script çalıştırmak değil, düzenli olarak geri yükleme testleri yapmak anlamına da gelir. Filtrelerin doğru çalıştığından emin olmanın en iyi yolu, zaman zaman bir test ortamına geri yükleme yapıp her şeyin yerli yerinde olduğunu doğrulamaktır.
