← все скрипты

backup-rotate.sh

bash ~ 45 строк обновлён 6 января 2026

Инкрементальный бэкап директорий с автоматической ротацией. Использует rsync с hard links для экономии места. Хранит заданное количество последних копий, остальные удаляет.

Зависимости

Использование

chmod +x backup-rotate.sh
./backup-rotate.sh /path/to/source /path/to/backups 7

Третий аргумент — количество хранимых копий (по умолчанию 7).

Код

#!/usr/bin/env bash
set -euo pipefail

# backup-rotate.sh — инкрементальный бэкап с ротацией
# Использование: ./backup-rotate.sh <source> <dest> [keep=7]

SOURCE="${1:?Укажите директорию-источник}"
DEST="${2:?Укажите директорию для бэкапов}"
KEEP="${3:-7}"

DATE=$(date +%Y-%m-%d_%H-%M-%S)
BACKUP_DIR="$DEST/$DATE"
LATEST_LINK="$DEST/latest"

# Создаём директорию для бэкапов, если не существует
mkdir -p "$DEST"

# rsync с hard links от предыдущего бэкапа
if [ -L "$LATEST_LINK" ]; then
    rsync -a --delete --link-dest="$LATEST_LINK" "$SOURCE/" "$BACKUP_DIR/"
else
    rsync -a --delete "$SOURCE/" "$BACKUP_DIR/"
fi

# Обновляем симлинк на последний бэкап
rm -f "$LATEST_LINK"
ln -s "$BACKUP_DIR" "$LATEST_LINK"

# Ротация: удаляем старые бэкапы
cd "$DEST"
BACKUPS=($(ls -d 20[0-9][0-9]-* 2>/dev/null | sort))
while [ "${#BACKUPS[@]}" -gt "$KEEP" ]; do
    echo "Удаляю старый бэкап: ${BACKUPS[0]}"
    rm -rf "${BACKUPS[0]}"
    BACKUPS=("${BACKUPS[@]:1}")
done

echo "Бэкап завершён: $BACKUP_DIR"
echo "Всего копий: ${#BACKUPS[@]} (лимит: $KEEP)"

Автоматизация через cron

Добавьте в crontab -e:

# Ежедневный бэкап в 3:00
0 3 * * * /opt/scripts/backup-rotate.sh /var/www /backups/www 14