18 апр. 2012 г.

Резервные копии баз данных в PostgreSQL

Как говорится, пока жареный петух в жо... собственно клюнул - сервер упал (думаю, что не без участия моих кривых ручек). "Самое время" организовать систему резервного копирования баз данных. Хоть какую-нибудь. Ну хотя бы самую простейшую. Но чтобы не делать это ручками каждый день, а чтоб само всё работало. И с каждым годом я все больше убеждаюсь в том, что компьютер нам нужен не только для создания нам различных проблем (чтобы мы их потом героически решали), но и для борьбы с проблемами, причём с некоторыми из них он вполне способен справляться сам, не впутывая нас в свои компьютерные дела. Но всё это лирика.

Переходим к физике. Итак, в наличие Ubuntu 11.10, PostgreSQL 9.1 и огромное желание заставить эту бездушную тварь компьютер делать всю чёрную работу за нас.
Как мы это будем делать? Нужен план! План будет такой:
  1. Нужен мегаумный скрипт, который будет делать копию базы данных, а лучше всех какие есть
  2. Делаем так, чтобы этот скрипт запускался сам автоматически и работал всю работу
Собственно всё! Да, план небольшой, но это не недостаток. Просто он такой план... болел в детстве много.
Итак,

Скрипт

Создаем скрипт такого содержания:
#!/bin/bash

# Инициализируем различные переменные для дальнейшей работы
# Папка, в которую будут складываться резервные копии
BACK_DIR="/mnt/backup/databases/postgre"

# Текущая дата и время для того, чтобы отличать одну копию от другой
DATE=`date +%Y%m%d%H%M%S`

# Лог файл для ошибок
ERRORLOGFILE=$BACK_DIR/error.log

# Получаем список всех баз данных в PostgreSQL
LIST=$(psql -l --host localhost --port 5432 --username "postgres" --no-password | awk '{ print $1}' | grep -vE '^-|^List|^Name|template[0|1]|^\(|\|')

for DATABASE in $LIST
do
   DB_BACK_DIR=$BACK_DIR/$DATABASE
   FILE=$DB_BACK_DIR/$DATABASE-$DATE.gz

# Создаем папку куда будет записана копия очередной базы данных
   mkdir -p $DB_BACK_DIR

# Делаем копию базы данных, сжимаем и складываем в созданную папку
   pg_dump --host localhost --port 5432 --username "postgres" --no-password $DATABASE | gzip -c > $FILE

# Проверяем наличие файла копии
   if [ -e $FILE ]
   then

# Копия создана, отправляем всплывающее сообщение, ибо нравица =)
      notify-send "Cron Info" "Database $DATABASE backed up"
   else

# Файл отсутствует. Создаем (если не создан) лог файл для ошибок, записываем туда, что что-то не так
      touch $ERRORLOGFILE
      ERRORMSG="$DATE. Something wrong with $DATABASE backup"
      echo $ERRORMSG >> $ERRORLOGFILE

# Ну и сообщение конечно же
      notify-send "Cron ERROR" $ERRORMSG
   fi

# На всякий случай делаем файл с копией базы доступным только нам и больше никому
   chown <user>:<group> $FILE
   chmod 0600 $FILE
done
Сохраняем куда-нибудь с любым именем, какое нравится (желательно без пробелов и латиницей) и разрешаем ему запускаться:
chmod +x /путь/к/скрипту
И не забудьте поменять пути к папкам и файлам на свои и <user>:<group> на своего пользователя в строке chown <user>:<group> $FILE
Теперь можно проверить как всё это работает (и работает ли вообще).
  • Открываем терминал (Ctrl+Alt+T)
  • Запускаем свой скрипт:
    >./путь/к/скрипту
Если все получилось (всплыли все сообщения и в нужной папке появились копии всех баз данных), то ставим галочку напротив первого пункта плана и переходим ко второму.

Автоматический запуск

Вариантов решить эту задачу море. Я предлагаю сделать умный вид и вспомнить слово cron. Cron - это такая штука, понимаешь, cron! Так вот, в ветке /etc есть 4 интересные нам папки:
  1. cron.hourly
  2. cron.daily
  3. cron.weekly
  4. cron.monthly
Как несложно догадаться в них нахдятся скрипты, которые выполняются каждый час, день, неделю и месяц. Куда определить свой скрипт - дело каждого. У меня резервные копии снимаются каждый день (благо базы небольшие и занимают немного места). Допустим необходимо снимать резервные копии ежедневно. Стало быть свой скрипт необходимо разместить в папке /etc/cron.daily, но мы опять сделаем умный вид и создадим там ссылку на наш скрипт. Открываем терминал и создаем ссылку:
ln -s /путь/к/скрипту /etc/cron.daily/postgrebackup
И вроде бы можно ставить галочку напротив второго пункта плана, но не тут-то было. И теперь выясним почему. Как можно было заметить в скрипте присутствуют такие команды как psql и pg_dump и в качестве параметров им передаются имя пользователя (--username "postgres") и параметр --no-password. Вот именно эта связка несколько запутывает. Создается впечатление, что мы соединяемся с PostgreSQL от имени администратора, но без пароля. На самом деле второй параметр вовсе не означает, что пароль не используется. Этот параметр всего лишь означает, что пароль не будет запрашиваться через консоль. А на самом деле пароль будет прочитан из файла ~/.pgpass. И вроде бы все хорошо. Пусть из файла. Мы же все проверили - скрипт работает. Да, он работает. Потому, что запускали мы его от своего имени и в нашей домашней папке такой файл есть (если нет, то его надо создать. посмотреть каков его формат можно в официальной документации). А cron запускает все скрипты от имени root, а стало быть такой файл также должен быть в папке /root. И как всегда, шестое чувство подсказывает, что нет там такого файла. Не беда!  Создадим там ссылку на наш файлик pgpass
ln -s ~/.pgpass /root/.pgpass
Вот теперь почти всё. Осталось проверить всё ли теперь работает так как надо. Для этого достаточно запустить наш скрипт от имени root.
sudo /путь/к/скрипту
Если всё сработало как надо, то ставим галочку напротив второго пункта плана.
Теперь эта железяка будет ежедневно снимать копии с баз. Вам лишь только надо будет периодически контролировать этот процесс.
И кстати этот процесс также можно автоматизировать. Но об этом в следующий раз.

Комментариев нет :