LinuxForum.Fans
Тема

Скрипт бэкапа баз данных PostgreSQL

Автор: Nigelist 20 сообщений 8373 просмотров
#225455

Хочу в будущем, написать скрипт бэкапа баз данных PostgreSQL. Определил для себя требования к скрипту:

  1. Делать бэкап без запроса пароля, с максимальным сжатием
  2. Возможность задавать кол-во хранимых бэкапов (при превышении допустимого кол-ва бэкапов, удалять самый старый)

Но не знаю, возможно ли в bash реализовать первый пункт?

Может кто-нибудь покажет, как реализовать второй пункт?

P.S. Сделал набросок скрипта, подскажите есть ли ошибки?

Показать
[console]#!/bin/bash
# Скрипт автоматического резервного копирования баз данных PostgreSQL

# Переменные
DBNAME1 = pharmbuh # Имя первой базы дынных, бэкап которой будет создаваться
DBNAME2 = pharmtorg # Имя второй базы данных, бэкап которой будет создаваться
BKUPDIR1 = /home/shared/backups/buh # Директория для бэкапов первой базы данных
BKUPDIR2 = /home/shared/backups/torg # Директория для бэкапов второй базы данных
BKUPDT = $(data +%Y.%m.%d) # Имя бэкапа в виде год-месяц-число
FNUM = 10 # Количество хранимых бэкапов

# Проверка количества бэкапов и удаление лишних бэкапов


# Начало резервного копирования баз данных PostgreSQL
pg_dump $DBNAME2 -Fc -Z9 -f $BKUPDIR2/data-$BKUPDT.dump.out[/console]
#225463
Nigelist написал:
Но не знаю, возможно ли в bash реализовать первый пункт?

не помню. лень искать. читайте ман, там просто.

Nigelist написал:
Может кто-нибудь покажет, как реализовать второй пункт?

/bin/ls -rt отсортирует бекапы по времени.
Нам надо удалить с Nного, по последний файл.
sed "1,${N}d" будет удалять первые строчки, т.е. файлы, которые надо оставить.
дальше xargs rm -v
только проверить надо. Я делал примерно так, УМВР, пишу по памяти.

#225464
Nigelist написал:
Сделал набросок скрипта, подскажите есть ли ошибки?

ну я делаю дамп в stdout, и сразу-же сжимаю. И возможно шифрую (а то если будет ошибка, врагам останется временный файл). Правда так сервер на дольше останавливается, хотя для постгре это вроде не так критично...

#225481
Nigelist написал:
Хочу в будущем, написать скрипт бэкапа баз данных PostgreSQL. Определил для себя требования к скрипту:

Я бы посмотрел в сторону fsbackup. Этот пакет, если склероз не изсеняет, могёт и PostgreSQL бэкапить. С твоими условиями...

#225550

Cruiser78, мне нужно делать бэкап средствами pg_dump. А этот скрипт я видел.

#225557
Nigelist написал:
Cruiser78, мне нужно делать бэкап средствами pg_dump. А этот скрипт я видел.

fsbackup - это только оболочка над "функционалом". Не скажу про Postgre, но дамп MySQL там внутри сливается через mysqldump (или как там его). Не думаю, что для Postgre - иначе. А если и иначе - что мешает тот скрипт чуток подправить в свою пользу? Заменить один вызов на другой?

#225569

Cruiser78, ок, гляну.

#243947

Если интересно - вот рабочий скрипт с логированием. Правда количество бэкапов не проверяет.

#!/bin/sh

fulldt="`date +%Y/%m/%d%t%a%t`"
dt="`date +%X%t`"

logfile="/root/postgres_cron_log/main_log.txt"
cmdlogfile="/root/postgres_cron_log/`date +%Y_%m_%d`_log.txt"

buhbase_dump_file="/postgres/dumps/buhbase_`date +%Y_%m_%d`"


printf "\n----------------------------------------------------\n" >> ${logfile}

printf "${fulldt}\n" >> ${logfile}

printf "`date +%X%t`STOPPING srvcv82..." >> ${logfile}
/etc/init.d/srv1cv82 stop >> ${cmdlogfile}
printf "OK\n" >> ${logfile}

printf "`date +%X%t`RESTARTING postgresql..." >> ${logfile}
/etc/init.d/postgresql restart >> ${cmdlogfile}
printf "OK\n" >> ${logfile}

printf "`date +%X%t`\"VACUUM FULL ANALYZE;\" for buhbase..." >> ${logfile}
psql -h localhost -U postgres -c "VACUUM FULL ANALYZE;" buhbase >> ${cmdlogfile}
printf "OK\n" >> ${logfile}

printf "`date +%X%t`WRITING DUMP for buhbase to \"/postgres/dumps/buhbase_dump\"..." >> ${logfile}
pg_dump -h localhost -U postgres -Fc -Z9 -c -f ${buhbase_dump_file} buhbase >> ${cmdlogfile}
printf "OK\n" >> ${logfile}

printf "`date +%X%t`STARTING srv1cv82..." >> ${logfile}
/etc/init.d/srv1cv82 start >> ${cmdlogfile}
printf "OK\n" >> ${logfile}

#243961

keller, я вот не пойму, как правильно указывать переменную в скрипте:
так?

text
$variable

или так?

text
${variable}
#243963
Nigelist написал:
keller, я вот не пойму, как правильно указывать переменную в скрипте:
так?
text
$variable

или так?

text
${variable}

Я читал, что это равнозначно. Можно и так и так.

#243965

Кстати насчет хранения файлов только определенного количества - то это мне надо только где базы с подчиненным узлом. На главном узле РИБ могут возникнуть у бухов желания восстановить за самый неожиданный период. Со временем я просто оставляю 2-3 дампа за месяц с интервалом 10 дней...

В любом случае полезно будет узнать как удалять лишние бэкапы автоматом.

Где-то встретил вот такое предложение. Но здесь получается ориентация на количество дней а не количество бэкапов. Но тоже неплохо.

# Удаляем файлы старше 10 дней
find $BACKUPDIR -mtime +10 -exec rm -f {} \;

#243971

keller, неплохо, но бэкапы у меня в выходные не создаются. Потому, мне нужно, чтобы ориентация была именно на кол-во дней. А по поводу взбрыков бухгалтеров, то у меня хранятся бэкапы за несколько лет, но их я создаю вручную, раз в месяц и раз в квартал.

"keller" написал:
Где-то встретил вот такое предложение. Но здесь получается ориентация на количество дней а не количество бэкапов. Но тоже неплохо.

# Удаляем файлы старше 10 дней
find $BACKUPDIR -mtime +10 -exec rm -f {} \;
Я встречал такое предложение здесь.
#244288
keller написал:
Кстати насчет хранения файлов только определенного количества - то это мне надо только где базы с подчиненным узлом.
В любом случае полезно будет узнать как удалять лишние бэкапы автоматом.

А в чем проблема то? Узнать количество файлов в каталоге очень просто:

text
total=` ls -1 | sed -n '$='`

Ну а дальше - делай в скрипте с этим total что хочешь... Получи список файлов и если текущий total больше заданного - отбери нужные и удали лишние файлы. Идея, надеюсь понятна.

#244292
"keller" написал:
В любом случае полезно будет узнать как удалять лишние бэкапы автоматом.

Ротация снимает все проблемы, я выше ссылку давал, скрипт:

text

#!/bin/bash
#  newzenon ..... http://linuxru.org/
#  по мотивам http://www.mikerubel.org/computers/rsync_snapshots/
#  
#  Скрипт делает резервные копии $SOURCE и их ротацию в директории $SNAPSHOT
#  Скрипт должен запускатся с двумя параметрами, название копии и количество
#  копий для сохранений.
#  
#     Запуск скрипта:
#     /usr/local/sbin/make_snapshot  < каталог> n
#          где
#          < каталог> - произвольное название каталога.
#          n          - чило копий для ротаций.
#
#  Пример:
#  Запуск для недельных ротаций:
#  make_snapshot weekly 7 (запускать раз в день из crontab)
#  0 0 * * 0 /usr/local/sbin/make_snapshot weekly 4
#
#  Запуск для ежедневных ротаций:
#  make_snapshot daily 7 (запускать 2 раза в день из crontab)
#  0 0 * * 1-2 /usr/local/sbin/make_snapshot daily 2
#
#  Итогом будет создание копий за семь дней:
#
#     Каталог для резервирования/ротаций: $SNAPSHOT
#     итого 40
#     drwxr-xr-x 10 root root 4096 Сен  8 15:42 .
#     drwxr-xr-x  5 root root 4096 Сен  8 15:32 ..
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:48 daily.0
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:48 daily.1
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:42 latest
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:42 weekly.0
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:42 weekly.1
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:42 weekly.2
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:42 weekly.3
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:41 weekly.4
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:41 weekly.5
#     dr-xr-xr-x  3 root root 4096 Сен  8 15:41 weekly.6

SOURCE=/var/www/my.syte.com # Каталог с которого делаем копию. SNAPSHOT=/home/backup # Каталог для копий.

error() { echo "$0: $@" 1>&2 exit 1 }

# Убеждаемся что запуск произведен от суперпользователя. if [ `id -u` != 0 ]; then error "You must be root to use this script"; fi

# Проверяем что запуск произведен с параметрами в коммандной строке. if [ "$1" = "" -o "$2" = "" ]; then echo "usage: $0 <snapshot type> <max snapshots>" exit 1 fi

type=$1 (( max = $2 - 1 ))

# Удаляем самый старый snapshot в фоновом режиме. if [ -d $SNAPSHOT/${type}.${max} ]; then mv $SNAPSHOT/${type}.${max} $SNAPSHOT/delete nice /bin/rm -rf $SNAPSHOT/delete & fi

# RSYNC. $SOURCE ==>> $SNAPSHOT/latest echo "------------------------------------------------" time rsync -pa --delete $SOURCE $SNAPSHOT/latest

# Делаем snapshot доступным только для чтения. chmod a-w $SNAPSHOT/latest

# Ротация (сдвиг) копий на однц позицию. Если они есть. while [ $max -ge 1 ]; do (( newer = max - 1 )) if [ -d $SNAPSHOT/${type}.${newer} ]; then mv $SNAPSHOT/${type}.${newer} $SNAPSHOT/${type}.${max} fi (( max = newer )) done

# Обновляем время доступа mtime для ${type}.0 mv $SNAPSHOT/latest $SNAPSHOT/${type}.0 touch $SNAPSHOT/${type}.0

# Make a hard-link-only (except for dirs) copy of the # latest snapshot to prepare for next snapshot. nice cp -al $SNAPSHOT/${type}.0 $SNAPSHOT/latest

# Ждем окончания выполнения rm если ещё работает. wait

# Вывод информации. echo "------------------------------------------------" echo "Резервируемый каталог: $SOURCE" echo "------------------------------------------------" echo "Каталог для резервирования/ротаций: $SNAPSHOT" echo "ls -la $SNAPSHOT" ls -la $SNAPSHOT echo "------------------------------------------------" echo Закончено: `date`

#244324

"Cruiser78" написал:
Ну а дальше - делай в скрипте с этим total что хочешь... Получи список файлов и если текущий total больше заданного - отбери нужные и удали лишние файлы. Идея, надеюсь понятна.
Не-а, я совсем не разбираюсь в bash. Если не сложно, напишите пожалуйста небольшой скрипт.
#244344
Nigelist написал:
Не-а, я совсем не разбираюсь в bash. Если не сложно, напишите пожалуйста небольшой скрипт.

Надо разбираться. Без этого знания заниматься юниксом невозможно.
Лови для общего развития:

text

#!/bin/sh
#создадим в текущем каталоге 20 файлов с именами a_NN для теста
LIMIT=20
for ((a=1; a <= LIMIT ; a++))
do
  touch a_$a
  sleep 1 # просто подождем, чтобы время изменилось 
done

# получим общее количество файлов в текущем каталоге # (для общего развития) total=`ls -1 -t a_* | sed -n '$='` echo total=$total

# пройдем по списку файлов в текущем каталоге # список отсортирован по дате создания файла # самый новый файл - самый верхний, самый старый - последний. count=0 maxfiles=5 for file in `ls -1 -t a_*` do echo $count: $file let count=$count+1 if [ $count -gt $maxfiles ]; then # Если счетчик файлов больше заданного значения - удалим старое файло rm -f $file echo $file deleted fi done

#244381

"Cruiser78" написал:
Надо разбираться. Без этого знания заниматься юниксом невозможно.
Лови для общего развития:
А если имя файла формируется с именем? Этот скрипт поймет?
#244464
Nigelist написал:
А если имя файла формируется с именем? Этот скрипт поймет?

Всё. Дальше сам. Я дал только пример, написанный специально максимально примитивно. Привязывай его к своим реалиям самостоятельно. Включай голову и разбирайся в написанном. Гугль в помощь.

#244488

"Cruiser78" написал:
Всё. Дальше сам. Я дал только пример, написанный специально максимально примитивно. Привязывай его к своим реалиям самостоятельно. Включай голову и разбирайся в написанном. Гугль в помощь.
Спасибо!
Войдите или зарегистрируйтесь, чтобы ответить.