На досуге решил поучитьcя немного написанию скриптов на шелле, а заодно и написать собственно скриптик, который бы регулярно бэкапил сайт, включая базу и статические файлы, а так же, удалял бы старые бэкапы, оставляя несколько последних. Вот что у меня получилось:
#!/bin/sh
# Задаём путь к файлам нашего сайта
# и к директории для хранения бэкапов:
SITEBACKUPDIR=/path/to/backups/mysite.ru
SITEDIR=/www/mysite.ru
# Задаём количество последних бэкапов, которые будем хранить:
NUMBACKUPS=6
# Если директория бэкапов не существует
# (вдруг случайно потёрли?), создаём её:
if [ -d $SITEBACKUPDIR ]
then :
else
mkdir -p $SITEBACKUPDIR
fi
# Переходим в директорию нашего сайта и снимаем дамп базы данных:
cd $SITEDIR
mysqldump -uUSER -pPASSWORD --databases --add-drop-table --quick DB_NAME > db_backup.sql
# Здесь USER и PASSWORD - имя и пароль пользователя БД;
# DB_NAME - база нашего сайта;
# --databases - позволяет воссоздать базу с нуля, если она будет
# отсутствовать;
# --add-drop-table - будет очищать базу перед восстановлением,
# что позволит избежать возможных проблем;
# --quick - пишем дамп сразу на диск - для экономии памяти,
# (если железо на сервере слабое).
# Затем упаковываем файлы сайта вместе с дампом базы в архив.
# При этом исключаем из бэкапа кэш сайта (--exclude=cache/*),
# чтобы уменьшить размер полученного архива.
# Имя архива, для удобства, задаём с временной меткой:
tar czf $SITEBACKUPDIR/mysite.ru-backup-`date +%Y-%m-%d-%H-%M-%S`.tar.gz --exclude=cache/* ./*
chmod 600 $SITEBACKUPDIR/mysite.ru-backup-*.tar.gz
# После завершения резервного копирования
# удаляем дамп базы из директории сайта:
rm -f ./db_backup.sql
cd $SITEBACKUPDIR
# Удаляем все бэкапы, кроме последних NUMBACKUPS:
x=1
for i in `ls -t`
do
if [ $x -le $NUMBACKUPS ]
then
let x++
continue
fi
rm $i
done
Скрипт делаем исполняемым и закрываем доступ к нему всем кроме владельца:
chmod 700 sitebackup
В завершение помещаем его в подходящую папку, например:
mv sitebackup /usr/bin
И прописываем его в crontab:
30 2 1 * * sitebackup
Таким образом, скрипт будет запускаться в 2:30, первого числа каждого месяца, делать бэкап, и удалять все бэкапы кроме последних NUMBACKUPS (в данном случае — 6).
Выгрузка бэкапов на удалённое хранилище.
В принципе, в этот же скрипт можно было бы добавить ещё несколько строк, чтобы бэкапы выгружались на наше файловое хранилище, например по FTP. Я выгружаю бэкапы на свой домашний роутер под управлением openwrt. Но т.к. роутер у меня смотрит в интернет из-за NAT, с серым IP, то инициировать FTP-соединение приходится не с хостинга, а с роутера. Для этого, под openwrt настроим FTP-клиент и напишем скриптик, который по крону будет забирать бэкапы с сервера.
Под линуксом в качестве FTP-клиента можно использовать консольную утилиту ftp (см. man ftp). Но т.к. в репозитории openwrt её не оказалось, я установил похожую утилиту — cmdftp:
opkg update
opkg install cmdftp
Вызов справки по опциям командной строки:
cmdftp -h
Подключение к FTP-серверу:
cmdftp -n ftp.mysite.ru
Затем вводим логин и пароль. Для справки по ftp-командам, используем команду ‘h’.
Наш скрипт будет подключаться по FTP к серверу, проверять содержимое папки с бэкапами и скачивавать бэкапы из неё на локальный диск:
#!/bin/sh
FTP_USER=USER
FTP_PASSWORD=PASSWORD
FTP_BACKUPDIR=/path/to/backups/mysite.ru
LOCAL_BACKUPDIR=/path/to/local/backups/mysite.ru
NUMBACKUPS=12
if [ -d $LOCAL_BACKUPDIR ]
then :
else
mkdir -p $LOCAL_BACKUPDIR
fi
cmdftp -n ftp.mysite.ru<<EOC
$FTP_USER
$FTP_PASSWORD
cd $FTP_BACKUPDIR
d mysite.ru-backup-*.tar.gz $LOCAL_BACKUPDIR
rename mysite.ru-backup-*.tar.gz -backup- -downloaded-backup-
bye
EOC
cd $LOCAL_BACKUPDIR
x=1
for i in `ls -t`
do
if [ $x -le $NUMBACKUPS ]
then
let x++
continue
fi
rm $i
done
Не забываем сделать скрипт исполняемым и, при необходимости, выставить на него нужные права доступа, после чего добавляем его в crontab:
30 4 1 * * sitebackup
Таким образом, скрипт будет в 4:30, первого числа каждого месяца скачивать резервные копии с сервера. Скрипт оставляет в локальном хранилище NUMBACKUPS последних архивов, удаляя все более старые. В данном случае будут храниться 12 последних архивов, то есть — ежемесячные резервные копии за год. По завершению загрузки, скрипт помечает на стороне сервера скачанные архивы, добавляя к имени файла «downloaded». Поэтому скрипт на стороне сервера можно изменить так, чтобы он удалял по маске те файлы, которые помечены скачанными:
cd $SITEBACKUPDIR
# Удаляем все бэкапы, помеченные скачанными:
rm -f mysite.ru-downloaded-backup-*.tar.gz
# Удаляем все бэкапы, кроме последних NUMBACKUPS:
x=1
for i in `ls -t`
do
if [ $x -le $NUMBACKUPS ]
then
let x++
continue
fi
rm $i
done
Функцию удаления старых архивов я оставил в скрипте на случай, если по какой-то причине роутер перестанет забирать архивы с сервера, чтобы не забивать дисковое пространство.
Полезные ссылки
lissyara.su — Программирование на языке командного интерпретатора — shell
linux.org.ru — Варианты счётчиков в shell скриптах
Блог Про Комп — Bash скрипт для удаления старых файлов
linuxcertif.com — man cmdftp