На днях ко мне обратился один из друзей и попросил сделать для его сайта
ежедневный бекап. Поискав в интернете, я наткнулся на несколько готовых
решений, часть из которых подразумевает установку дополнительного
софта. Данные варианты меня не устроили, хотелось чего-то более узкого и
простого. Так я пришел к решению сделать свой скрипт. Вот что в итоге
получилось.
Основная задача в следующем: в качестве движка сайта установлен форум
IPB. Сами скрипты весят не много, однако папка uploads
имеет довольно внушительный вес и ее необходимо бекапить в первую
очередь. Так же необходимо бекапить и базу данных. Подумав, я решил, что
скрипты и база данных будут бекапиться отдельно, а папка uploads
будет каждый раз апдейтиться из существующей. Даже если файл удалить,
он останется в бекапе, а если изменить, будет создана его версированную
копию.
И так. Необходимо создать три папки:
scripts — будут собираться скрипты
bd — дампы базы данных
uploads — папка с загруженными файлами.
В папках
scripts и bd создадим еще три папки:
daily — ежедневные бекапы (за 7 дней)
weekly — еженедельные бекапы (за месяц)
monthly — ежемесячные бекапы (за 3 месяца)
Далее, как только бекапы будут сделаны, данные автоматически синхронизируются с моим хранилищем по
Rsync.
Итак, вот сам скрипт с комментариями:
#!/bin/bash # Данная строка необходима, чтобы отправлять по почте письма с русскими символами export LC_CTYPE=ru_RU.UTF-8
# Основная настройка
# Имя проекта NAME="project" # Путь к проекту TARGET_DIR="/srv/www/vhosts/blablabla/html" # Путь к бекапам BACKUP_DIR="/backups" # Email для отчетов EMAIL="agentsib@mycoolname.me"
# Настройка базы данных MYSQL_USER="user" MYSQL_PASSWORD="pass" MYSQL_DATABASE="base"
# Настройка Rsync клиента для синхронизации RSYNC_PASSWORD="mypass" RSYNC_USER="agentsib" RSYNC_HOST="IP_SERVER" RSYNC_LINK="/backups/${NAME}"
if [[ `echo $TERM ` == "xterm" ]]; then ISTERM=true ; fi // Запись в лог файл и вывод на экран function log { if [ $ISTERM ]; then echo "`date +"%Y.%m.%d %H:%M:%S" ` ${1}" ; fi echo "`date +"%Y.%m.%d %H:%M:%S" ` ${1}" >> ${BACKUP_DIR}/logs/t-log.log }
#Создаем структуру каталогов, если она отсутствует
if [ ! -d ${BACKUP_DIR} ]; then mkdir ${BACKUP_DIR} ; fi
if [ ! -d ${BACKUP_DIR}/scripts ]; then mkdir ${BACKUP_DIR}/scripts ; fi if [ ! -d ${BACKUP_DIR}/bd ]; then mkdir ${BACKUP_DIR}/bd ; fi
if [ ! -d ${BACKUP_DIR}/scripts/daily ]; then mkdir ${BACKUP_DIR}/scripts/daily ; fi if [ ! -d ${BACKUP_DIR}/scripts/weekly ]; then mkdir ${BACKUP_DIR}/scripts/weekly ; fi if [ ! -d ${BACKUP_DIR}/scripts/monthly ]; then mkdir ${BACKUP_DIR}/scripts/monthly ; fi
if [ ! -d ${BACKUP_DIR}/bd/daily ]; then mkdir ${BACKUP_DIR}/bd/daily ; fi if [ ! -d ${BACKUP_DIR}/bd/weekly ]; then mkdir ${BACKUP_DIR}/bd/weekly ; fi if [ ! -d ${BACKUP_DIR}/bd/monthly ]; then mkdir ${BACKUP_DIR}/bd/monthly ; fi
if [ ! -d ${BACKUP_DIR}/uploads ]; then mkdir ${BACKUP_DIR}/uploads ; fi
if [ ! -d ${BACKUP_DIR}/logs ]; then mkdir ${BACKUP_DIR}/logs ; fi
# чистим старые логи rm ${BACKUP_DIR}/logs/*
log '--------------------------------' log 'Скрипт дампа запущен'; log '--------------------------------' log '' log 'Бекапим скрипты' log ''
# Если ежедневный архив еще не создавался - сделаем это
if [ -f ${BACKUP_DIR}/scripts/daily/${NAME}-`date +%F`.tar.gz ]; then log "Дневной архив (${NAME}-`date +%F`.tar.gz) уже создан!" else log '' log "Создаем ежедневный архив ${BACKUP_DIR}/scripts/daily/${NAME}-`date +%F`.tar.gz" # Архивируем нашу папку. Обращаю внимание, что папка uploads не архивируется tar -czf ${BACKUP_DIR}/scripts/daily/${NAME}-`date +%F`.tar.gz --exclude ${TARGET_DIR}/forum/uploads ${TARGET_DIR}/*
# создаем еженедельный архив, если его не было. Простым копированием ежедневного. Формат - называние-номернедели if [ ! -f ${BACKUP_DIR}/scripts/weekly/${NAME}-`date +%V`.tar.gz ]; then log "Создаем еженедельный архив ${BACKUP_DIR}/scripts/weekly/${NAME}-`date +%V`.tar.gz" cp ${BACKUP_DIR}/scripts/daily/${NAME}-`date +%F`.tar.gz ${BACKUP_DIR}/scripts/weekly/${NAME}-`date +%V`.tar.gz fi # создаем ежемесячный архив, принцип такой же как и у еженедельного if [ ! -f ${BACKUP_DIR}/scripts/monthly/${NAME}-`date +%Y.%m`.tar.gz ]; then log "Создаем ежемесячный архив ${BACKUP_DIR}/scripts/monthly/${NAME}-`date +%Y.%m`.tar.gz" cp ${BACKUP_DIR}/scripts/daily/${NAME}-`date +%F`.tar.gz ${BACKUP_DIR}/scripts/monthly/${NAME}-`date +%Y.%m`.tar.gz fi #Чистим устаревшие бекапы FILES_FOR_DEL=`find ${BACKUP_DIR}/scripts/daily/* -mtime +7` if [ "${FILES_FOR_DEL}" != "" ]; then log '' log 'Удаляем старые ежедневные дампы: ' log $FILES_FOR_DEL log '' fi FILES_FOR_DEL=`find ${BACKUP_DIR}/scripts/weekly/* -mtime +37` if [ "${FILES_FOR_DEL}" != "" ]; then log '' log 'Удаляем старые еженедельные дампы: ' log $FILES_FOR_DEL log '' fi FILES_FOR_DEL=`find ${BACKUP_DIR}/scripts/monthly/* -mtime +120` if [ "${FILES_FOR_DEL}" != "" ]; then log '' log 'Удаляем старые ежемесячные дампы: ' log $FILES_FOR_DEL log '' fi cp -Ru --backup=existing ${TARGET_DIR}/forum/uploads/* ${BACKUP_DIR}/uploads/ fi log '' log 'Бекапим базу данных' log ''
# ничего нового, все тоже самое, только для базы if [ -f ${BACKUP_DIR}/bd/daily/${NAME}-`date +%F`.tar.gz ]; then log "Дневной архив (${NAME}-`date +%F`.tar.gz) уже создан!" else log '' log "Создаем ежедневный архив ${BACKUP_DIR}/bd/daily/${NAME}-`date +%F`.tar.gz" # сливаем дамп и архивируем его mysqldump -u${MYSQL_USER} -p"${MYSQL_PASSWORD}" \ -c -i -K --single-transaction --add-drop-table -B "${MYSQL_DATABASE}" \ > ${BACKUP_DIR}/bd/daily/${NAME}-`date +%F`.sql cd ${BACKUP_DIR}/bd/daily/ tar -czf ${BACKUP_DIR}/bd/daily/${NAME}-`date +%F`.tar.gz ${NAME}-`date +%F`.sql rm ${BACKUP_DIR}/bd/daily/${NAME}-`date +%F`.sql if [ ! -f ${BACKUP_DIR}/bd/weekly/${NAME}-`date +%V`.tar.gz ]; then log "Создаем еженедельный архив ${BACKUP_DIR}/bd/weekly/${NAME}-`date +%V`.tar.gz" cp ${BACKUP_DIR}/bd/daily/${NAME}-`date +%F`.tar.gz ${BACKUP_DIR}/bd/weekly/${NAME}-`date +%V`.tar.gz fi if [ ! -f ${BACKUP_DIR}/bd/monthly/${NAME}-`date +%Y.%m`.tar.gz ]; then log "Создаем ежемесячный архив ${BACKUP_DIR}/bd/monthly/${NAME}-`date +%Y.%m`.tar.gz" cp ${BACKUP_DIR}/bd/daily/${NAME}-`date +%F`.tar.gz ${BACKUP_DIR}/bd/monthly/${NAME}-`date +%Y.%m`.tar.gz fi FILES_FOR_DEL=`find ${BACKUP_DIR}/bd/daily/* -mtime +7` if [ "${FILES_FOR_DEL}" != "" ]; then log '' log 'Удаляем старые ежедневные дампы: ' log $FILES_FOR_DEL log '' fi FILES_FOR_DEL=`find ${BACKUP_DIR}/bd/weekly/* -mtime +37` if [ "${FILES_FOR_DEL}" != "" ]; then log '' log 'Удаляем старые еженедельные дампы: ' log $FILES_FOR_DEL log '' fi FILES_FOR_DEL=`find ${BACKUP_DIR}/bd/monthly/* -mtime +120` if [ "${FILES_FOR_DEL}" != "" ]; then log '' log 'Удаляем старые ежемесячные дампы: ' log $FILES_FOR_DEL log '' fi fi
log '--------------------------------' log 'Скрипт выполнен' log '--------------------------------'
# Данная строка необходима, чтобы Rsync не запрашивал пароль export RSYNC_PASSWORD="${RSYNC_PASSWORD}"
# отчитываемся на мыло, что сделано mail -r backup@lemial.net -s "Отчет бекапа" "$EMAIL" < ${BACKUP_DIR}/logs/t-log.log
# синхронизируем файлы с удаленным сервером, обращаю внимание на то, что папка с логами игнорируется. rsync -auv --delete-after ${BACKUP_DIR}/* --exclude ${BACKUP_DIR}/logs rsync://${RSYNC_USER}@${RSYNC_HOST}${RSYNC_LINK} >> ${BACKUP_DIR}/logs/t-logrs.log
# отсылаем лог Rsync mail -r backup@lemial.net -s "Отчет RSync" "$EMAIL" < ${BACKUP_DIR}/logs/t-logrs.log
Далее прописываем скрипт в крон, чтобы он выполнялся хотя бы раз в сутки. Вот и все, удачи.
Отдельная благодарность Павлу Краснопевцеву за помощь со скриптами :)
|