بکاپ خودکار روزانه از MySQL با cron و حذف بکاپهای قدیمی
بکاپ دستی همیشه فراموش میشود. در این راهنما یک اسکریپت امن و ساده مینویسیم که هر شب از دیتابیس بکاپ فشرده میگیرد، بکاپهای قدیمیتر از چند روز را حذف میکند و نتیجه را در لاگ مینویسد.
۱ساخت پوشهٔ بکاپ و فایل اتصال
پوشهٔ بکاپ را جدا از پوشهٔ دیتابیس بسازید و فقط برای root قابل خواندن کنید. اتصال را با ~/.my.cnf انجام دهید تا رمز در اسکریپت نباشد.
sudo mkdir -p /var/backups/mysql
sudo chmod 700 /var/backups/mysql
sudo tee /root/.my.cnf > /dev/null <<'EOF'
[client]
user=backup
password=YOUR_STRONG_PASSWORD
EOF
sudo chmod 600 /root/.my.cnf۲نوشتن اسکریپت بکاپ
اسکریپت زیر ابتدا در فایل موقت مینویسد و فقط در صورت موفقیت آن را نهایی میکند؛ پس اگر mysqldump وسط کار خطا بدهد فایل ناقص بهعنوان بکاپ باقی نمیماند.
sudo tee /usr/local/bin/mysql-backup.sh > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
DB_NAME="appdb"
BACKUP_DIR="/var/backups/mysql"
KEEP_DAYS=14
STAMP=$(date +%F_%H-%M)
OUT="$BACKUP_DIR/${DB_NAME}_${STAMP}.sql.gz"
trap 'rm -f "$OUT.tmp"' ERR
mysqldump --single-transaction --quick --routines --triggers --events \
--no-tablespaces "$DB_NAME" | gzip > "$OUT.tmp"
gzip -t "$OUT.tmp"
mv "$OUT.tmp" "$OUT"
# حذف بکاپهای قدیمیتر از KEEP_DAYS روز
find "$BACKUP_DIR" -name "${DB_NAME}_*.sql.gz" -mtime +"$KEEP_DAYS" -delete
echo "$(date '+%F %T') OK $OUT ($(du -h "$OUT" | cut -f1))"
EOF
sudo chmod 700 /usr/local/bin/mysql-backup.shبرای چند دیتابیس، DB_NAME را حلقه کنید یا بهجای آن از --all-databases استفاده کنید.
۳اجرای دستی برای تست
قبل از زمانبندی، یک بار اسکریپت را دستی اجرا کنید و خروجی و فایل ساختهشده را ببینید.
sudo /usr/local/bin/mysql-backup.sh
ls -lh /var/backups/mysql/۴زمانبندی با cron
با crontab -e (برای root) خط زیر را اضافه کنید تا هر شب ساعت ۳ اجرا شود و خروجی در لاگ ذخیره شود. ساعت کمترافیک سایت را انتخاب کنید.
sudo crontab -e
# هر شب ساعت 03:00
0 3 * * * /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1بعد از اولین اجرای خودکار حتماً لاگ را ببینید: tail /var/log/mysql-backup.log
۵چرخش لاگ خود بکاپ
با logrotate جلوی بزرگ شدن فایل لاگ را بگیرید.
sudo tee /etc/logrotate.d/mysql-backup > /dev/null <<'EOF'
/var/log/mysql-backup.log {
weekly
rotate 8
compress
missingok
notifempty
}
EOF۶کپی بکاپ روی سرور دیگر
بکاپی که فقط روی همان سرور باشد با خراب شدن سرور از بین میرود. بعد از بکاپ، آن را با rsync به یک سرور یا فضای ذخیرهسازی دیگر بفرستید. این خط را به انتهای اسکریپت اضافه کنید.
rsync -az --delete -e "ssh -i /root/.ssh/backup_key" \
/var/backups/mysql/ backup@203.0.113.20:/srv/backups/mysql/قانون ۳-۲-۱: حداقل سه نسخه، روی دو نوع رسانهٔ متفاوت و یک نسخه بیرون از محل اصلی.
۷بررسی دورهای ریستور
ماهی یک بار یکی از بکاپها را روی یک دیتابیس آزمایشی ریستور کنید و تعداد رکوردهای جدولهای اصلی را مقایسه کنید. تنها همین کار ثابت میکند بکاپها واقعاً قابل استفادهاند.
mysql -e "CREATE DATABASE restore_test"
zcat /var/backups/mysql/appdb_2026-09-29_03-00.sql.gz | mysql restore_test
mysql -e "SELECT COUNT(*) FROM restore_test.users"
mysql -e "DROP DATABASE restore_test"پرسشهای پرتکرار دربارهٔ بکاپ خودکار روزانه از MySQL با cron و حذف بکاپهای قدیمی
بکاپها را چند روز نگه دارم؟
معمولاً ۷ تا ۳۰ روز روزانه، بهعلاوهٔ یک بکاپ ماهانه برای مدت طولانیتر. به حجم دیسک و میزان تغییر داده بستگی دارد؛ تعداد روزها را با KEEP_DAYS تنظیم کنید.
چرا cron بکاپ نگرفت؟
معمولاً بهخاطر مسیر ناقص دستورها (در cron از /usr/local/bin/ و مسیر کامل استفاده کنید)، دسترسی نداشتن فایل اجرایی (chmod +x) یا نبودن ~/.my.cnf برای کاربر اجراکنندهٔ cron است. لاگ را با grep CRON /var/log/syslog ببینید.