Rsync ile E-posta Bildirimi: Hata Uyarı Sistemi Nasıl Kurulur
Yedekleme işleri sessiz sedasız çalışırken her şey güzel görünür. Asıl sorun, bir şeyler ters gittiğinde haberdar olamamaktır. Rsync scriptiniz gece yarısı hata verdi, disk doldu, hedef sunucuya bağlanılamadı — ve siz sabah gelip her şeyin yolunda olduğunu sanıyorsunuz. İşte bu yazıda tam da bu senaryoyu çözüyoruz: rsync ile entegre, akıllı bir e-posta bildirim sistemi kuruyoruz.
Neden E-posta Bildirimi Şart?
Cron job olarak çalışan rsync scriptleri genellikle gözden kaçar. Log dosyası var mı? Belki. Ama o log dosyasını her sabah kontrol eden var mı? Büyük ihtimalle hayır. Monitoring sistemleri bu işi çözüyor elbette, ama her ortamda Nagios, Zabbix veya Prometheus kurmak mümkün olmayabiliyor. Basit, güvenilir ve kurulumu beş dakika süren bir çözüme ihtiyaç var.
E-posta bildirim sistemi üç temel senaryoyu kapsamalı:
- Başarısız yedeklemeler: Rsync sıfır dışı bir exit code döndürdüğünde
- Kısmi başarılar: Yedekleme tamamlandı ama bazı dosyalar atlandı
- Başarılı yedeklemeler: İsteğe bağlı olarak, her şey yolundaysa da haber ver
Biz burada hepsini ele alacağız ve üzerine disk doluluk kontrolü, yedekleme boyutu anomali tespiti gibi ekstralar da koyacağız.
Temel Araçlar ve Gereksinimler
Başlamadan önce sistemde nelerin kurulu olması gerektiğine bakalım.
Mail gönderimi için seçenekler:
- mailx / mail: En basit yöntem, sistemde genellikle hazır gelir
- sendmail: Klasik MTA, yapılandırması karmaşık olabilir
- msmtp: Harici SMTP sunucusu için hafif ve kolay yapılandırılır
- ssmtp: Eski ama hala çalışan basit SMTP relay
Kurumsal ortamlarda genellikle dahili bir SMTP relay bulunur. Ev veya küçük ortamlarda Gmail SMTP veya benzeri bir servis kullanılır. Biz her iki senaryoyu da göstereceğiz.
msmtp Kurulumu ve Yapılandırması
# Ubuntu/Debian
sudo apt-get install msmtp msmtp-mta mailutils
# CentOS/RHEL/Rocky Linux
sudo dnf install msmtp mailx
Gmail SMTP için yapılandırma dosyası oluşturalım:
cat > /etc/msmtprc << 'EOF'
# Varsayılan değerler
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log
# Gmail hesabı
account gmail
host smtp.gmail.com
port 587
from [email protected]
user [email protected]
password BURAYA_UYGULAMA_SIFRESI
# Varsayılan hesap
account default : gmail
EOF
chmod 600 /etc/msmtprc
Gmail kullanıyorsanız hesap ayarlarından “Uygulama Şifresi” oluşturmanız gerekiyor. Normal hesap şifrenizi buraya yazmayın.
Test edelim:
echo "Test mesajı" | mail -s "Msmtp Test" [email protected]
Temel Rsync Bildirim Scripti
Önce işlevsel ama basit bir script yazalım, sonra üzerine katman katman özellik ekleyelim.
#!/bin/bash
# /usr/local/bin/rsync-backup.sh
# Temel rsync yedekleme scripti e-posta bildirimi ile
# --- Yapılandırma ---
KAYNAK="/var/www /home /etc"
HEDEF="/mnt/backup/gunluk"
UZAK_HEDEF="[email protected]:/backup/sunucu1"
LOG_DOSYASI="/var/log/rsync-backup.log"
HATA_LOG="/var/log/rsync-backup-error.log"
BILDIRIM_EMAIL="[email protected]"
SUNUCU_ADI=$(hostname -f)
TARIH=$(date '+%Y-%m-%d %H:%M:%S')
TARIH_KISA=$(date '+%Y%m%d_%H%M%S')
# --- Rsync Parametreleri ---
RSYNC_OPTS="-avz --delete --stats --human-readable
--exclude='*.tmp'
--exclude='*.log'
--exclude='/proc/*'
--exclude='/sys/*'
--log-file=${LOG_DOSYASI}"
# --- Fonksiyonlar ---
email_gonder() {
local KONU="$1"
local MESAJ="$2"
echo -e "$MESAJ" | mail -s "$KONU" "$BILDIRIM_EMAIL"
}
# --- Yedekleme Başlıyor ---
echo "[$TARIH] Yedekleme başladı" >> "$LOG_DOSYASI"
BASLANGIC_ZAMANI=$(date +%s)
# Rsync çalıştır, hata çıktısını ayır
rsync $RSYNC_OPTS "$KAYNAK" "$UZAK_HEDEF" 2>"$HATA_LOG"
EXIT_CODE=$?
BITIS_ZAMANI=$(date +%s)
SURE=$((BITIS_ZAMANI - BASLANGIC_ZAMANI))
# --- Sonucu Değerlendir ---
if [ $EXIT_CODE -eq 0 ]; then
echo "[$TARIH] Yedekleme başarıyla tamamlandı. Süre: ${SURE}s" >> "$LOG_DOSYASI"
# Başarı bildirimi (isteğe bağlı, yoğun ortamlarda kapatılabilir)
email_gonder
"[BASARILI] $SUNUCU_ADI Yedekleme - $TARIH"
"Yedekleme başarıyla tamamlandı.nnSunucu: $SUNUCU_ADInTarih: $TARIHnSüre: ${SURE} saniyenKaynak: $KAYNAKnHedef: $UZAK_HEDEF"
else
HATA_MESAJI=$(cat "$HATA_LOG")
echo "[$TARIH] HATA! Exit code: $EXIT_CODE" >> "$LOG_DOSYASI"
email_gonder
"[HATA] $SUNUCU_ADI Yedekleme Başarısız - $TARIH"
"HATA: Yedekleme başarısız oldu!nnSunucu: $SUNUCU_ADInTarih: $TARIHnExit Code: $EXIT_CODEnKaynak: $KAYNAKnHedef: $UZAK_HEDEFnnHata Detayı:n$HATA_MESAJI"
fi
Bu script çalışıyor ama henüz kaba. Şimdi gerçek dünyada işe yarayacak şekilde geliştirelim.
Rsync Exit Code’larını Anlamak
Rsync farklı hata durumlarında farklı exit code’lar döndürür. Bu kodları yorumlamak, anlamlı hata mesajları göndermenizi sağlar.
rsync_hata_acikla() {
local KOD=$1
case $KOD in
0) echo "Başarılı" ;;
1) echo "Syntax hatası veya kullanım hatası" ;;
2) echo "Protokol uyumsuzluğu" ;;
3) echo "Kaynak veya hedef dosya seçim hatası" ;;
4) echo "İstenen aksiyon desteklenmiyor" ;;
5) echo "Başlatma hatası" ;;
6) echo "Log yazma hatası" ;;
10) echo "Hata - Soket I/O hatası" ;;
11) echo "Hata - Dosya I/O hatası" ;;
12) echo "Hata - Rsync protokol veri akış hatası" ;;
13) echo "Hata - Teşhis kodu için program hatası" ;;
14) echo "Hata - IPC kodu hatası" ;;
20) echo "Sinyal alındı, işlem sonlandırıldı" ;;
21) echo "Waitpid() çağrısında hata" ;;
22) echo "Bellek tahsis hatası" ;;
23) echo "Kısmi transfer - bazı dosyalar aktarılamadı" ;;
24) echo "Kısmi transfer - bazı kaynak dosyalar kayboldu" ;;
25) echo "Silme limiti aşıldı" ;;
30) echo "Timeout - veri gönderme/alma zaman aşımı" ;;
35) echo "Timeout - bağlantı zaman aşımı" ;;
255) echo "SSH bağlantı hatası" ;;
*) echo "Bilinmeyen hata kodu: $KOD" ;;
esac
}
Exit code 23 özellikle dikkat etmeniz gereken bir durum. Yedekleme tamamlandı görünüyor ama bazı dosyalar aktarılamadı. İzinler, kilitli dosyalar, bozuk filesystem gibi durumlarda oluşur.
Gelişmiş Bildirim Sistemi
Şimdi production ortamına uygun, kapsamlı bir script yazalım. Bu script disk kontrolü, yedek boyut anomali tespiti ve HTML e-posta desteği içeriyor.
#!/bin/bash
# /usr/local/bin/rsync-smart-backup.sh
# Gelişmiş rsync yedekleme ve bildirim sistemi
set -euo pipefail
# ============================================
# YAPILANDIRMA
# ============================================
SUNUCU_ADI=$(hostname -f)
KAYNAK_DIZINLER=("/var/www/html" "/home" "/etc" "/opt/uygulama")
UZAK_HEDEF="[email protected]:/backup/${SUNUCU_ADI}"
SSH_KEY="/root/.ssh/backup_rsa"
SSH_PORT="22"
# Log ayarları
LOG_DIR="/var/log/rsync-backup"
LOG_DOSYASI="${LOG_DIR}/backup-$(date '+%Y%m%d').log"
HATA_LOG="${LOG_DIR}/error-$(date '+%Y%m%d').log"
ISTATISTIK_LOG="${LOG_DIR}/stats-$(date '+%Y%m%d_%H%M%S').log"
# E-posta ayarları
BILDIRIM_EMAIL="[email protected]"
BILDIRIM_EMAIL_CC="[email protected]"
GONDEREN="[email protected]"
HATA_DURUMUNDA_BILDIR=true
BASARI_DURUMUNDA_BILDIR=false # Çok fazla mail gelmesini önler
KISMI_HATA_BILDIR=true
# Eşik değerleri
MIN_YEDEK_BOYUTU_MB=100 # Yedek bu değerden küçükse uyar
DISK_DOLU_ESIK=85 # Disk doluluk yüzdesi eşiği
SURE_ESIK_DAKIKA=120 # Bu süreden uzun sürerse uyar
ONCEKI_BOYUT_SAPMA_YUZDESI=30 # Önceki yedeğe göre boyut farkı eşiği
# Durum dosyası (önceki yedek boyutunu saklar)
DURUM_DOSYASI="/var/lib/rsync-backup/son-durum.dat"
# ============================================
# FONKSIYONLAR
# ============================================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_DOSYASI"
}
hata_log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] HATA: $1" | tee -a "$LOG_DOSYASI" "$HATA_LOG"
}
dizin_hazirla() {
mkdir -p "$LOG_DIR"
mkdir -p "$(dirname "$DURUM_DOSYASI")"
}
disk_kontrol() {
local HEDEF_IP="${UZAK_HEDEF%%:*}"
local HEDEF_YOLU="${UZAK_HEDEF##*:}"
# Uzak disk kullanımını kontrol et
local DISK_KULLANIM
DISK_KULLANIM=$(ssh -i "$SSH_KEY" -p "$SSH_PORT" -o ConnectTimeout=10
"${HEDEF_IP}" "df -h ${HEDEF_YOLU} | tail -1 | awk '{print $5}'" 2>/dev/null | tr -d '%')
if [ -n "$DISK_KULLANIM" ] && [ "$DISK_KULLANIM" -gt "$DISK_DOLU_ESIK" ]; then
echo "UYARI: Hedef disk %${DISK_KULLANIM} dolu (eşik: %${DISK_DOLU_ESIK})"
return 1
fi
return 0
}
boyut_anomali_kontrol() {
local MEVCUT_BOYUT=$1
if [ ! -f "$DURUM_DOSYASI" ]; then
log "İlk çalışma, boyut referansı oluşturuluyor: ${MEVCUT_BOYUT}MB"
echo "$MEVCUT_BOYUT" > "$DURUM_DOSYASI"
return 0
fi
local ONCEKI_BOYUT
ONCEKI_BOYUT=$(cat "$DURUM_DOSYASI")
if [ "$ONCEKI_BOYUT" -eq 0 ]; then
echo "$MEVCUT_BOYUT" > "$DURUM_DOSYASI"
return 0
fi
local FARK_YUZDESI
FARK_YUZDESI=$(echo "scale=0; (($MEVCUT_BOYUT - $ONCEKI_BOYUT) * 100) / $ONCEKI_BOYUT" | bc 2>/dev/null || echo "0")
FARK_YUZDESI=${FARK_YUZDESI#-} # Mutlak değer
echo "$MEVCUT_BOYUT" > "$DURUM_DOSYASI"
if [ "$FARK_YUZDESI" -gt "$ONCEKI_BOYUT_SAPMA_YUZDESI" ]; then
echo "UYARI: Yedek boyutu anomalisi tespit edildi! Önceki: ${ONCEKI_BOYUT}MB, Mevcut: ${MEVCUT_BOYUT}MB (fark: %${FARK_YUZDESI})"
return 1
fi
return 0
}
html_email_olustur() {
local DURUM=$1
local KONU_DETAY=$2
local ICERIK=$3
local SURE=$4
local BOYUT=$5
local EXIT_CODE=$6
local RENK
case $DURUM in
"BASARILI") RENK="#28a745" ;;
"HATA") RENK="#dc3545" ;;
"UYARI") RENK="#ffc107" ;;
*) RENK="#6c757d" ;;
esac
cat << HTML
Content-Type: text/html; charset=UTF-8
Subject: [$DURUM] $SUNUCU_ADI Yedekleme - $KONU_DETAY
From: Yedekleme Sistemi <$GONDEREN>
To: $BILDIRIM_EMAIL
Cc: $BILDIRIM_EMAIL_CC
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"></head>
<body style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<div style="background-color: ${RENK}; color: white; padding: 20px; border-radius: 5px 5px 0 0;">
<h2 style="margin: 0;">Yedekleme Raporu: $DURUM</h2>
<p style="margin: 5px 0 0 0;">${SUNUCU_ADI} - $(date '+%d.%m.%Y %H:%M')</p>
</div>
<div style="background-color: #f8f9fa; padding: 20px; border: 1px solid #dee2e6;">
<table style="width: 100%; border-collapse: collapse;">
<tr><td style="padding: 5px; font-weight: bold;">Sunucu:</td><td>${SUNUCU_ADI}</td></tr>
<tr><td style="padding: 5px; font-weight: bold;">Tarih:</td><td>$(date '+%d.%m.%Y %H:%M:%S')</td></tr>
<tr><td style="padding: 5px; font-weight: bold;">Süre:</td><td>${SURE} saniye</td></tr>
<tr><td style="padding: 5px; font-weight: bold;">Boyut:</td><td>${BOYUT}</td></tr>
<tr><td style="padding: 5px; font-weight: bold;">Exit Code:</td><td>${EXIT_CODE}</td></tr>
<tr><td style="padding: 5px; font-weight: bold;">Hedef:</td><td>${UZAK_HEDEF}</td></tr>
</table>
</div>
<div style="background-color: #ffffff; padding: 20px; border: 1px solid #dee2e6; border-top: 0;">
<pre style="background: #f1f1f1; padding: 10px; overflow-x: auto; font-size: 12px;">${ICERIK}</pre>
</div>
<div style="background-color: #e9ecef; padding: 10px; text-align: center; font-size: 12px; color: #6c757d; border-radius: 0 0 5px 5px;">
Bu mesaj otomatik olarak oluşturulmuştur. Lütfen yanıtlamayın.
</div>
</body>
</html>
HTML
}
bildirim_gonder() {
local DURUM=$1
local KONU_DETAY=$2
local ICERIK=$3
local SURE=${4:-0}
local BOYUT=${5:-"Bilinmiyor"}
local EXIT_CODE=${6:-0}
log "E-posta bildirimi gönderiliyor: [$DURUM] $KONU_DETAY"
html_email_olustur "$DURUM" "$KONU_DETAY" "$ICERIK" "$SURE" "$BOYUT" "$EXIT_CODE" |
sendmail -t 2>/dev/null ||
echo -e "Durum: $DURUMnDetay: $ICERIK" |
mail -s "[$DURUM] $SUNUCU_ADI Yedekleme - $KONU_DETAY"
-c "$BILDIRIM_EMAIL_CC" "$BILDIRIM_EMAIL"
}
# ============================================
# ANA SCRIPT
# ============================================
dizin_hazirla
log "=========================================="
log "Yedekleme başlıyor: $SUNUCU_ADI"
log "Kaynak dizinler: ${KAYNAK_DIZINLER[*]}"
log "Hedef: $UZAK_HEDEF"
BASLANGIC=$(date +%s)
GENEL_EXIT_CODE=0
HATA_MESAJLARI=""
UYARI_MESAJLARI=""
# SSH bağlantı testi
log "SSH bağlantısı test ediliyor..."
if ! ssh -i "$SSH_KEY" -p "$SSH_PORT" -o ConnectTimeout=15 -o BatchMode=yes
"${UZAK_HEDEF%%:*}" "exit 0" 2>/dev/null; then
hata_log "SSH bağlantısı başarısız: ${UZAK_HEDEF%%:*}"
bildirim_gonder "HATA" "SSH Bağlantı Hatası $(date '+%d.%m.%Y %H:%M')"
"SSH bağlantısı kurulamadı!nHedef: ${UZAK_HEDEF%%:*}nAnahtar: $SSH_KEY"
"0" "N/A" "255"
exit 1
fi
# Disk kontrolü
DISK_UYARI=$(disk_kontrol 2>&1) || UYARI_MESAJLARI+="$DISK_UYARIn"
# Her kaynak dizin için rsync çalıştır
for KAYNAK in "${KAYNAK_DIZINLER[@]}"; do
if [ ! -d "$KAYNAK" ]; then
log "UYARI: Kaynak dizin bulunamadı, atlanıyor: $KAYNAK"
UYARI_MESAJLARI+="Kaynak dizin mevcut değil: $KAYNAKn"
continue
fi
log "Yedekleniyor: $KAYNAK"
rsync -avz
--delete
--stats
--human-readable
--timeout=300
-e "ssh -i $SSH_KEY -p $SSH_PORT -o ConnectTimeout=30"
--exclude='*.tmp' --exclude='*.swp' --exclude='__pycache__'
--exclude='node_modules/' --exclude='.git/'
--log-file="$ISTATISTIK_LOG"
"$KAYNAK" "$UZAK_HEDEF" 2>>"$HATA_LOG"
RSYNC_KOD=$?
if [ $RSYNC_KOD -ne 0 ] && [ $RSYNC_KOD -ne 23 ] && [ $RSYNC_KOD -ne 24 ]; then
GENEL_EXIT_CODE=$RSYNC_KOD
HATA_MESAJLARI+="$KAYNAK dizini yedeklenirken hata (kod: $RSYNC_KOD): $(rsync_hata_acikla $RSYNC_KOD 2>/dev/null || echo 'Hata')n"
elif [ $RSYNC_KOD -eq 23 ] || [ $RSYNC_KOD -eq 24 ]; then
UYARI_MESAJLARI+="$KAYNAK: Kısmi transfer (kod: $RSYNC_KOD) - bazı dosyalar aktarılamadın"
fi
done
BITIS=$(date +%s)
TOPLAM_SURE=$((BITIS - BASLANGIC))
# Süre kontrolü
if [ $TOPLAM_SURE -gt $((SURE_ESIK_DAKIKA * 60)) ]; then
UYARI_MESAJLARI+="Yedekleme beklenenden uzun sürdü: ${TOPLAM_SURE}s (eşik: $((SURE_ESIK_DAKIKA * 60))s)n"
fi
# Yedek boyut kontrolü
AKTARILAN_BOYUT=$(grep "Total transferred file size" "$ISTATISTIK_LOG" 2>/dev/null |
awk '{print $NF}' | tail -1 || echo "0M")
# Bildirim kararı
if [ $GENEL_EXIT_CODE -ne 0 ]; then
log "Yedekleme BAŞARISIZ. Exit code: $GENEL_EXIT_CODE"
if [ "$HATA_DURUMUNDA_BILDIR" = true ]; then
ICERIK="Yedekleme BAŞARISIZ!nnHATALAR:n${HATA_MESAJLARI}"
[ -n "$UYARI_MESAJLARI" ] && ICERIK+="nUYARILAR:n${UYARI_MESAJLARI}"
ICERIK+="nnLog: $LOG_DOSYASInHata Log: $HATA_LOG"
bildirim_gonder "HATA" "Yedekleme Başarısız $(date '+%d.%m.%Y %H:%M')"
"$ICERIK" "$TOPLAM_SURE" "$AKTARILAN_BOYUT" "$GENEL_EXIT_CODE"
fi
elif [ -n "$UYARI_MESAJLARI" ]; then
log "Yedekleme UYARI ile tamamlandı."
if [ "$KISMI_HATA_BILDIR" = true ]; then
bildirim_gonder "UYARI" "Yedekleme Uyarıları $(date '+%d.%m.%Y %H:%M')"
"Yedekleme tamamlandı ancak uyarılar var:nn${UYARI_MESAJLARI}"
"$TOPLAM_SURE" "$AKTARILAN_BOYUT" "0"
fi
else
log "Yedekleme BAŞARILI. Süre: ${TOPLAM_SURE}s"
if [ "$BASARI_DURUMUNDA_BILDIR" = true ]; then
bildirim_gonder "BASARILI" "$(date '+%d.%m.%Y %H:%M')"
"Tüm dizinler başarıyla yedeklendi."
"$TOPLAM_SURE" "$AKTARILAN_BOYUT" "0"
fi
fi
log "Yedekleme işlemi tamamlandı."
exit $GENEL_EXIT_CODE
Cron ile Zamanlama ve Log Rotasyonu
# Script'i çalıştırılabilir yap
chmod +x /usr/local/bin/rsync-smart-backup.sh
# Cron job ekle - her gece 02:30'da çalıştır
crontab -e
Cron girişi:
# Rsync yedekleme - her gece 02:30
30 2 * * * /usr/local/bin/rsync-smart-backup.sh >> /var/log/rsync-backup/cron.log 2>&1
# Log rotasyonu için /etc/logrotate.d/rsync-backup dosyası oluştur
Log rotasyon yapılandırması:
cat > /etc/logrotate.d/rsync-backup << 'EOF'
/var/log/rsync-backup/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 640 root adm
dateext
dateformat -%Y%m%d
}
EOF
Anlık Test ve Sorun Giderme
Script’i cron’a almadan önce mutlaka test edin:
# Dry-run ile test et, gerçekte kopyalama yapma
rsync -avzn --stats
-e "ssh -i /root/.ssh/backup_rsa"
/var/www/html [email protected]:/backup/test/
# Script'i debug modunda çalıştır
bash -x /usr/local/bin/rsync-smart-backup.sh
# Mail gönderilebilirliğini test et
echo "Test maili - $(date)" | mail -s "Rsync Backup Test" [email protected]
# SSH anahtarının doğru çalıştığını kontrol et
ssh -i /root/.ssh/backup_rsa -o BatchMode=yes [email protected] "echo 'SSH OK'"
Sık karşılaşılan sorunlar ve çözümleri:
- Mail gönderilmiyor:
mail.logveyasyslog‘u kontrol edin.journalctl -u postfixile MTA durumuna bakın - SSH bağlantı hatası: Anahtarın izinlerinin
600olduğunu,authorized_keys‘e eklendiğini kontrol edin - Cron’da çalışmıyor, terminalde çalışıyor: PATH sorunu olabilir. Script’in başına
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binekleyin - Exit code 23 sürekli geliyor:
/proc,/sys,/rungibi sanal dosya sistemlerini exclude listesine alın
Gerçek Dünya Senaryosu: E-ticaret Sitesi Yedeklemesi
Diyelim ki WooCommerce tabanlı bir e-ticaret siteniz var. Veritabanı ayrı yedekleniyor, ama medya dosyaları, theme ve plugin dosyaları rsync ile yedekleniyor.
#!/bin/bash
# /usr/local/bin/woocommerce-backup.sh
KAYNAK_DIZINLER=("/var/www/html/wp-content/uploads" "/var/www/html/wp-content/themes" "/var/www/html/wp-content/plugins")
HEDEF="[email protected]:/backup/eticaret"
KRITIK_BOYUT_MB=500 # Uploads klasörü bu değerin altına düşerse kritik uyarı
for DIZIN in "${KAYNAK_DIZINLER[@]}"; do
BOYUT_MB=$(du -sm "$DIZIN" 2>/dev/null | cut -f1)
if [ "$DIZIN" = "/var/www/html/wp-content/uploads" ] &&
[ "$BOYUT_MB" -lt "$KRITIK_BOYUT_MB" ]; then
echo "KRİTİK: Uploads klasörü çok küçük! ${BOYUT_MB}MB (beklenen: min ${KRITIK_BOYUT_MB}MB)" |
mail -s "[KRİTİK] Uploads Boyut Anomalisi" [email protected]
fi
done
Bu tür bir kontrol, uploads klasörünün yanlışlıkla silindiği veya mount noktasının kaybedildiği durumları erken tespit eder.
Sonuç
Rsync tek başına güçlü bir araç, ama e-posta bildirimi olmadan kör uçuş yapıyorsunuz. Anlattığımız sistemin özeti şu:
- Exit code yorumlama ile hangi hatanın ne anlama geldiğini e-postada açıkça belirtiyorsunuz
- Disk doluluk ve boyut anomali kontrolü ile reaktif değil proaktif davranıyorsunuz
- HTML e-posta formatı ile mobil cihazdan bile hızlıca durumu kavrayabiliyorsunuz
- Log rotasyonu ile disk şişmesini önlüyorsunuz
- SSH bağlantı testi ile rsync başlamadan önce olası bağlantı sorunlarını yakalıyorsunuz
Bu sistemi bir kere kurup unutabilirsiniz. Bir şeyler ters gittiğinde e-posta sizi uyaracak. Uyarı gelmediğinde ise yedeklerinizin sağlıklı çalıştığından emin olabilirsiniz. Yedekleme sistemlerinin asıl amacı da tam olarak bu: sessizce çalışmak, ama gerektiğinde bağırabilmek.
