Rsync Hata Ayıklama ve Log Yönetimi
Yedekleme işlemlerinde en çok sinir bozan şey nedir biliyor musun? Sabah işe geliyorsun, gece çalışması gereken rsync job’ı başarısız olmuş, ama neden başarısız olduğunu anlamak için saatler harcıyorsun. Log yok, hata mesajı belirsiz, ya da tam tersine o kadar çok log var ki içinden çıkamıyorsun. İşte bu yazıda rsync’in hata ayıklama mekanizmalarını ve log yönetimini derinlemesine inceleyeceğiz. Gerçek dünyada karşılaşılan sorunları ele alacağız ve “bu neden çalışmıyor?” sorusuna sistematik cevaplar bulmayı öğreneceğiz.
Rsync’in Çıkış Kodlarını Anlamak
Rsync her çalışma sonucunda bir çıkış kodu döndürür. Bu kodları anlamak, otomatik yedekleme scriptlerinde hata yönetiminin temelini oluşturur.
En sık karşılaşılan çıkış kodları şunlardır:
- 0: Başarılı tamamlama
- 1: Sözdizimi veya kullanım hatası
- 2: Protokol uyumsuzluğu
- 3: Giriş/çıkış hatası (dosya seçiminde)
- 5: Başlatma hatası
- 10: Soket I/O hatası (ağ bağlantısı koptu)
- 11: Dosya I/O hatası
- 12: Rsync protokol veri akışı hatası
- 23: Bazı dosyalar aktarılamadı (kısmi başarı)
- 24: Bazı dosyalar aktarım sırasında silindi (kaynak değişti)
- 25: –max-delete limiti aşıldı
- 30: Zaman aşımı hatası
- 35: Bağlantı zaman aşımı
Özellikle kod 23 çok önemlidir. Pek çok sysadmin bu kodu görünce “bir şeyler yanlış gitti” diye panikler, oysa bu sadece bazı dosyaların atlındığını gösterir. Belki bir dosya aktarım sırasında değişti, belki izin sorunu vardı. Kritik mi değil mi, bunu log’a bakarak anlayacaksın.
#!/bin/bash
# Çıkış kodu kontrolü ile akıllı yedekleme scripti
rsync -avz --delete /data/web/ [email protected]:/backup/web/
EXIT_CODE=$?
case $EXIT_CODE in
0)
echo "$(date): Yedekleme başarıyla tamamlandı" >> /var/log/backup.log
;;
23)
echo "$(date): UYARI - Bazı dosyalar aktarılamadı (kod 23), detay için rsync.log kontrol edin" >> /var/log/backup.log
# Kod 23'ü kritik hata saymıyoruz ama bildiriyoruz
exit 0
;;
24)
echo "$(date): UYARI - Bazı dosyalar aktarım sırasında değişti (kod 24)" >> /var/log/backup.log
exit 0
;;
*)
echo "$(date): KRİTİK HATA - Rsync başarısız oldu, çıkış kodu: $EXIT_CODE" >> /var/log/backup.log
# Alarm gönder
mail -s "Yedekleme Başarısız! Sunucu: $(hostname)" [email protected] < /var/log/backup.log
exit 1
;;
esac
Verbose ve Debug Seçenekleri
Rsync’in ne yaptığını görmek için çeşitli verbosity seviyeleri vardır.
- -v: Temel verbose, hangi dosyaların transfer edildiğini gösterir
- -vv: Daha ayrıntılı çıktı, atlanan dosyalar dahil
- -vvv: Maximum debug seviyesi, protokol detayları
- –progress: Aktif transfer ilerlemesini gösterir
- –stats: Transfer istatistiklerini özetle gösterir
- –itemize-changes: Her dosya için ne yapıldığını gösterir (çok güçlü!)
- –dry-run (-n): Gerçekte hiçbir şey yapmadan neyin olacağını gösterir
--itemize-changes seçeneği özellikle güçlüdür. Her dosya için 11 karakterlik bir format kodu gösterir:
# itemize-changes çıktısını anlama
rsync -avzn --itemize-changes /source/ /destination/
# Örnek çıktı:
# >f.st...... dosya.txt -> dosya değişti (boyut veya zaman)
# >f++++++++++ yeni_dosya.txt -> yeni dosya eklendi
# .d..t....... dizin/ -> dizin zamanı değişti
# *deleting eski_dosya.txt -> silinecek dosya
# Format: YXcstpoguax
# Y: > (transfer edilecek), < (alınacak), c (yerel değişim), h (hard link), . (değişim yok)
# X: f (dosya), d (dizin), L (symlink), D (cihaz), S (özel dosya)
# c: checksum farklı
# s: boyut farklı
# t: zaman farklı
# p: izinler farklı
# o: sahip farklı
# g: grup farklı
Log Dosyası Yapılandırması
Rsync’in log yönetimi için birkaç farklı yaklaşım mevcuttur.
–log-file Kullanımı
En basit yaklaşım --log-file parametresidir:
rsync -avz
--log-file=/var/log/rsync/backup_$(date +%Y%m%d).log
--log-file-format="%t [%p] %o %f %l"
/data/ [email protected]:/backup/
# Log format parametreleri:
# %t: zaman damgası
# %p: PID
# %o: operasyon (send/recv/del)
# %f: dosya adı
# %l: dosya boyutu
# %b: transfer edilen byte sayısı
# %e: hata kodu (varsa)
# %i: itemize kodu
Gelişmiş Log Yapısı
Üretim ortamlarında log dosyalarını düzenli tutmak önemlidir. Tarih bazlı log yapısı kuralım:
#!/bin/bash
# /usr/local/bin/rsync-backup.sh
LOG_DIR="/var/log/rsync"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="$LOG_DIR/backup_${DATE}.log"
SUMMARY_FILE="$LOG_DIR/summary.log"
# Log dizinini oluştur
mkdir -p "$LOG_DIR"
# Rsync komutu
rsync -avz
--delete
--stats
--log-file="$LOG_FILE"
--log-file-format="%t [%i] [%o] %n%L (%b bytes)"
--exclude='*.tmp'
--exclude='*.cache'
--exclude='.git/'
/var/www/html/
[email protected]:/backup/web/ 2>&1
EXIT_CODE=$?
# Özet bilgiyi summary log'a ekle
echo "$(date '+%Y-%m-%d %H:%M:%S') | Exit: $EXIT_CODE | Log: $LOG_FILE" >> "$SUMMARY_FILE"
# 30 günden eski logları temizle
find "$LOG_DIR" -name "backup_*.log" -mtime +30 -delete
exit $EXIT_CODE
Rsyncd Sunucu Tarafı Log Yönetimi
Eğer rsync daemon modunda (rsyncd) çalışıyorsa, sunucu tarafında da log yönetimi yapman gerekir.
/etc/rsyncd.conf dosyasında log yapılandırması:
# /etc/rsyncd.conf
uid = rsync
gid = rsync
use chroot = yes
max connections = 4
pid file = /var/run/rsyncd.pid
# Global log ayarları
log file = /var/log/rsyncd.log
log format = %t %a %m %f %b
transfer logging = yes
syslog facility = local5
[web_backup]
path = /backup/web
comment = Web Sunucu Yedekleri
read only = no
auth users = webbackup
secrets file = /etc/rsyncd.secrets
# Modül bazlı log
log file = /var/log/rsync/web_backup.log
refuse options = checksum delete
Syslog entegrasyonu için /etc/rsyslog.d/rsync.conf dosyası oluşturabilirsin:
# /etc/rsyslog.d/rsync.conf
local5.* /var/log/rsync/rsyncd.log
# Bu ayarın ardından rsyslog'u yeniden başlat
systemctl restart rsyslog
Gerçek Dünya Senaryosu 1: “Transfer Çok Yavaş” Sorunu
Bir müşteri aramı aradı, “gece yedeklemesi 2 saatte bitiyordu, şimdi 8 saate çıktı” dedi. Teşhis süreci şöyle oldu:
# Önce --stats ile genel bir bakış
rsync -avz --stats --dry-run /data/production/ [email protected]:/backup/ 2>&1 | tee /tmp/rsync_stats.txt
# Çıktıyı incele
grep -E "(files|bytes|speedup)" /tmp/rsync_stats.txt
# Checkpoint: Her N dosyadan sonra ilerlemeyi göster
rsync -avz --info=progress2 /data/production/ [email protected]:/backup/
# Bant genişliğini ölç
rsync -avz --bwlimit=0 --stats /data/production/ [email protected]:/backup/ 2>&1 | grep "bytes/sec"
Sorun ortaya çıktı: Biri production sunucusuna 47 GB’lık log dosyası bırakmıştı ve bu dosya her gece transfer ediliyordu. --exclude ile çözdük ama asıl önemli olan log analizi sayesinde bunu hızlıca tespit edebildik.
# Büyük dosyaları tespit etmek için
rsync -avzn --out-format="%l %n" /data/production/ [email protected]:/backup/ |
sort -rn | head -20
Gerçek Dünya Senaryosu 2: SSH Bağlantı Hataları
Uzak rsync işlemlerinde SSH kaynaklı sorunlar çok yaygındır. Debug yaklaşımı:
# SSH bağlantısını ayrı test et
ssh -v [email protected] "echo SSH OK"
# Rsync'e SSH debug parametresi geç
rsync -avz -e "ssh -v -i /root/.ssh/backup_key"
/data/ [email protected]:/backup/ 2>&1 | tee /tmp/rsync_ssh_debug.log
# SSH timeout sorunları için
rsync -avz -e "ssh -o ConnectTimeout=30 -o ServerAliveInterval=60 -o ServerAliveCountMax=3"
/data/ [email protected]:/backup/
# StrictHostKeyChecking sorunu (ilk bağlantı)
rsync -avz -e "ssh -o StrictHostKeyChecking=no"
/data/ [email protected]:/backup/
Genellikle karşılaşılan SSH hata mesajları ve çözümleri:
- “Host key verification failed”:
ssh-keyscan -H 192.168.1.100 >> ~/.ssh/known_hostsile çöz - “Permission denied (publickey)”: SSH anahtar dosyasının izinlerini kontrol et,
chmod 600 ~/.ssh/backup_keyolmalı - “Connection timed out”: Firewall kurallarını kontrol et, sunucu tarafında port 22 açık mı?
- “Broken pipe”:
ServerAliveIntervalveServerAliveCountMaxile SSH keepalive ayarla
Hata Toleranslı Yedekleme Scripti
Tüm bu bilgileri birleştiren, production ortamına hazır bir script:
#!/bin/bash
# /usr/local/bin/smart-backup.sh
# Kullanım: ./smart-backup.sh <kaynak> <hedef> <job_adı>
set -euo pipefail
# Yapılandırma
SOURCE="${1:-/data}"
DEST="${2:[email protected]:/backup}"
JOB_NAME="${3:-backup}"
LOG_DIR="/var/log/rsync"
MAX_RETRY=3
RETRY_DELAY=60
MAIL_TO="[email protected]"
# Renkli çıktı
RED='33[0;31m'
YELLOW='33[1;33m'
GREEN='33[0;32m'
NC='33[0m'
# Loglama fonksiyonu
log() {
local level="$1"
local message="$2"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo -e "${timestamp} [${level}] ${message}" | tee -a "$LOG_FILE"
}
# Log dosyasını hazırla
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/${JOB_NAME}_$(date +%Y%m%d_%H%M%S).log"
LOCK_FILE="/tmp/rsync_${JOB_NAME}.lock"
# Çakışma kontrolü
if [ -f "$LOCK_FILE" ]; then
OLD_PID=$(cat "$LOCK_FILE")
if kill -0 "$OLD_PID" 2>/dev/null; then
log "ERROR" "Başka bir $JOB_NAME işlemi çalışıyor (PID: $OLD_PID)"
exit 1
else
log "WARN" "Eski lock dosyası temizleniyor"
rm -f "$LOCK_FILE"
fi
fi
echo $$ > "$LOCK_FILE"
trap "rm -f $LOCK_FILE" EXIT
# Retry mekanizması
attempt=0
while [ $attempt -lt $MAX_RETRY ]; do
attempt=$((attempt + 1))
log "INFO" "Deneme $attempt/$MAX_RETRY başlıyor: $SOURCE -> $DEST"
rsync -avz
--delete
--stats
--log-file="$LOG_FILE"
--log-file-format="%t [%i] %n (%b bytes)"
--timeout=300
--partial
--partial-dir=".rsync-partial"
-e "ssh -o ConnectTimeout=30 -o ServerAliveInterval=60 -o BatchMode=yes"
--exclude='*.tmp' --exclude='*.swp' --exclude='.git/'
"$SOURCE" "$DEST"
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ] || [ $EXIT_CODE -eq 24 ]; then
log "INFO" "${GREEN}Yedekleme başarılı (kod: $EXIT_CODE)${NC}"
break
elif [ $EXIT_CODE -eq 23 ]; then
log "WARN" "${YELLOW}Kısmi başarı (kod 23) - bazı dosyalar atlandı${NC}"
break
else
log "ERROR" "${RED}Deneme $attempt başarısız (kod: $EXIT_CODE)${NC}"
if [ $attempt -lt $MAX_RETRY ]; then
log "INFO" "$RETRY_DELAY saniye beklenip tekrar denenecek"
sleep $RETRY_DELAY
fi
fi
done
# Sonuç raporu
if [ $EXIT_CODE -ne 0 ] && [ $EXIT_CODE -ne 23 ] && [ $EXIT_CODE -ne 24 ]; then
log "ERROR" "Tüm denemeler başarısız oldu!"
mail -s "[ALARM] Yedekleme Başarısız: $JOB_NAME @ $(hostname)"
"$MAIL_TO" < "$LOG_FILE"
exit 1
fi
# Eski logları temizle
find "$LOG_DIR" -name "${JOB_NAME}_*.log" -mtime +30 -delete
log "INFO" "30 günden eski loglar temizlendi"
exit 0
Logrotate ile Log Yönetimi
Rsync logları zamanla büyüyebilir. Logrotate ile otomatik yönetim:
# /etc/logrotate.d/rsync
/var/log/rsync/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 640 root adm
dateext
dateformat -%Y%m%d
postrotate
# Eğer rsyncd daemon çalışıyorsa HUP gönder
if [ -f /var/run/rsyncd.pid ]; then
kill -HUP $(cat /var/run/rsyncd.pid) 2>/dev/null || true
fi
endscript
}
/var/log/rsync/summary.log {
weekly
rotate 12
compress
delaycompress
missingok
notifempty
}
Log Analizi ve İzleme
Biriken loglardan anlamlı bilgi çıkarmak için bazı pratik komutlar:
# Son 7 günün başarı/başarısızlık oranı
grep -E "(başarılı|HATA|başarısız)" /var/log/rsync/summary.log |
tail -n 50 |
awk '{print $1, $2, $NF}' |
column -t
# Transfer edilen toplam veri miktarı
grep "Total transferred file size" /var/log/rsync/backup_*.log |
awk '{print $NF}' |
awk '{sum += $1} END {print "Toplam: " sum/1024/1024 " MB"}'
# En sık atlanan dosyalar (hatalı transferler)
grep "cannot" /var/log/rsync/backup_*.log |
awk '{print $NF}' | sort | uniq -c | sort -rn | head -10
# Yavaş transferleri tespit et (30 dakikadan uzun sürenler)
awk '/başlıyor/{start=$1} /başarılı/{
end=$1
diff = end - start
if (diff > 1800) print "Yavaş transfer: " diff " saniye"
}' /var/log/rsync/summary.log
# Belirli bir tarihteki tüm hatalar
grep "2024-01-15" /var/log/rsync/backup_*.log | grep -i "error|fail|cannot"
Systemd Journal ile Entegrasyon
Modern Linux sistemlerinde rsync işlemlerini systemd service olarak tanımlamak log yönetimini kolaylaştırır:
# /etc/systemd/system/rsync-backup.service
[Unit]
Description=Rsync Yedekleme Servisi
After=network.target
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/smart-backup.sh /data [email protected]:/backup web_backup
StandardOutput=journal
StandardError=journal
SyslogIdentifier=rsync-backup
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/rsync-backup.timer
[Unit]
Description=Gece 02:00 Rsync Yedekleme
Requires=rsync-backup.service
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
# Servisi etkinleştir
systemctl daemon-reload
systemctl enable rsync-backup.timer
systemctl start rsync-backup.timer
# Journal'dan logları izle
journalctl -u rsync-backup.service -f
journalctl -u rsync-backup.service --since "2024-01-01" --until "2024-01-31"
# Sadece hataları göster
journalctl -u rsync-backup.service -p err
Checksums ile Veri Bütünlüğü Doğrulama
Yedeklemenin doğru yapıldığından emin olmak için checksum doğrulaması:
# Checksum bazlı karşılaştırma (daha yavaş ama güvenilir)
rsync -avz --checksum
--log-file=/var/log/rsync/checksum_verify.log
/data/critical/ [email protected]:/backup/critical/
# Yedekleme sonrası doğrulama scripti
#!/bin/bash
SOURCE="/data/critical"
DEST="[email protected]:/backup/critical"
DIFF_LOG="/var/log/rsync/integrity_check_$(date +%Y%m%d).log"
echo "Bütünlük kontrolü başlıyor: $(date)" > "$DIFF_LOG"
# Dry-run ile checksum karşılaştırması
rsync -avzn --checksum
--out-format="FARK: %n (kaynak: %l bytes)"
"$SOURCE/" "$DEST/" >> "$DIFF_LOG" 2>&1
DIFF_COUNT=$(grep -c "^FARK:" "$DIFF_LOG" || true)
if [ "$DIFF_COUNT" -gt 0 ]; then
echo "UYARI: $DIFF_COUNT dosyada tutarsızlık tespit edildi!" | tee -a "$DIFF_LOG"
mail -s "Yedekleme Bütünlük Uyarısı: $DIFF_COUNT dosya farklı" [email protected] < "$DIFF_LOG"
else
echo "OK: Tüm dosyalar tutarlı" | tee -a "$DIFF_LOG"
fi
Sonuç
Rsync hata ayıklama ve log yönetimi, “çalışıyor mu çalışmıyor mu” sorusundan çok ötede bir konu. İyi yapılandırılmış bir log sistemi sana şunu sağlar: bir sorun çıktığında saatlerce uğraşmak yerine dakikalar içinde neyin yanlış gittiğini anlayabilirsin.
En önemli çıkarımları özetleyecek olursam:
- Çıkış kodlarını her zaman kontrol et, özellikle 23 ve 24 kodlarına özel muamele yap
--itemize-changesve--statsseçeneklerini production loglarına dahil et, fazladan yer kaplar ama sorun anında altın değeri taşır- Retry mekanizması olmayan bir yedekleme scripti eksik bir scripttir, geçici ağ sorunları için mutlaka ekle
- Log dosyalarını logrotate ile yönet, disk dolup sunucu durmasın
- Systemd timer ile cron yerine modern yedekleme zamanlaması kullan, journal entegrasyonu sayesinde merkezi log yönetimi kolaylaşır
- Düzenli bütünlük kontrolleri yap, “yedekleme var” demek “yedekleme çalışıyor ve veri tutarlı” demek değildir
Bu konuyu bir kez doğru kurarsın, sonrasında yedekleme sistemi seni değil, sen yedekleme sistemini yönetirsin.
