LINUX.ORG.RU

Улучшенный сценарий архивации PostgreSQL

 ,


4

3

Доработав сценарий, делюсь, может кому будет полезно. Кроме того внимательно выслушаю замечания.

root@PostgreSQL:/home/maintainer# cat /root/backup.sh
#!/bin/bash

FILENAME='/root/psql_dblist'
PORT=5433
USERNAME='dbadmin'
SERVERNAME='localhost'
ARCHIVEDIR='/Backup'
SUFFIX=''
ADMINSEMAILS='email@gmail.com email@yandex.ru'
NETDIR='//192.168.88.11/Kamin/PostgreSQL'
EMFROM="email@mail.su"
ERRLOG="/root/backup.txt"
EMSMTP="192.168.88.232:25"
EMPASS="Pa$$w0rd"


if [[ 'daily' = $1 ]]
then
    SUFFIX='daily_'$(date +%u)'_'$(date +%H)
    #echo $SUFFIX
    #echo Ok
fi

if [[ 'monthly' = $1 ]]
then
    SUFFIX='monthly_'$(date +%b)'_'$(date +%H)
fi

if [[ 'hot' = $1 ]]
then
    SUFFIX='hot_'$(date +%Y-%b-%d-%H%M)
fi

if [[ $SUFFIX = '' ]]
then
    echo 'Type monthly, daily or hot as parametr'
    exit
fi


if mount | grep -qw $NETDIR
then
    echo "Network directory is mounted"
else
    echo "Network direcrory $NETDIR is not mounted" >> $ERRLOG
    SUBJECT="PostgeSQL:NoGood SUFFUX=$SUFFIX"
    MESSAGE="File /root/backup.txt contain some errors. Look for attachment"
    sendEmail -f $EMFROM -t $ADMINSEMAILS -u $SUBJECT -m $MESSAGE -s $EMSMTP -xu $EMFROM -xp $EMPASS -o tls=no -q -a $ERRLOG
    exit
fi

#DBLIST=$(psql -U $USERNAME -p $PORT -l | awk '/psql/ { print $1 }')
DBLIST=$(psql -U $USERNAME -p $PORT -l | q -d'|' "select c1 from - where c1 <> '' and c2 <> '' and c1 not like 'template%' limit 1,10000")

echo "$DBLIST" > $FILENAME

cat ${FILENAME} | while read DBNAME;
do
    mkdir -p ${ARCHIVEDIR}'/'${DBNAME};
    pg_dump -d $DBNAME -h ${SERVERNAME} -p $PORT -U ${USERNAME} -w | gzip > ${ARCHIVEDIR}'/'${DBNAME}'/'${DBNAME}'_'$SUFFIX'.dump.gz';
    #pg_dump -d $DBNAME -h ${SERVERNAME} -p $PORT -U ${USERNAME} -w | gzip > ${ARCHIVEDIR}'/'${DBNAME}'/'${DBNAME}'_'$(date +%Y-%b-%d-%H%M)'.dump.gz';
done


read BackupErr < /root/backup.txt
SUBJECT=''
MESSAGE=''

if [[ $BackupErr = '' ]]
then
    SUBJECT="Archiving PostgeSQL:Ok SUFFUX=$SUFFIX"
    MESSAGE="Archiving successful. File /root/backup.txt is empry."
else
    SUBJECT="PostgeSQL:NoGood SUFFUX=$SUFFIX"
    MESSAGE="File /root/backup.txt contain some errors. Look for attachment"
fi

sendEmail -f $EMFROM -t $ADMINSEMAILS -u $SUBJECT -m $MESSAGE -s $EMSMTP -xu $EMFROM -xp $EMPASS -o tls=no -q -a $ERRLOG

Добавлено уведомление о результате по e-mail. Оптимизации кода пока нет. На это тоже нужно время и самое главное время на тестирование.

root@PostgreSQL:/home/maintainer# crontab -l
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
0       8,12,16,20      *       *       *       /root/backup.sh daily 2>> /root/backup.txt
0       4       15      *       *       /root/backup.sh monthly 2>> /root/backup.txt

Кроме того внимательно выслушаю замечания.

NETDIR='//192.168.88.11/Kamin/PostgreSQL'
# skip
EMSMTP="192.168.88.232:25"

Если это реальные ip'шники в локальной сети, то в глобальную сеть их лучше не выкладывать, т. к. потенциальный взломщик, взломав какой-нибудь сервер с внешним интерфейсом, уже заранее будет что-то знать о структуре вашей сети, что, в свою очередь, упростит и ускорит взлом других, внутренних серверов. Разумеется, если выхода в Инет нет совсем и не планируется, то всё, что я сказал выше, — неактуально.

aureliano15 ()

if
if
if

Для кого case придумали?

echo «$DBLIST» > $FILENAME
cat ${FILENAME} | while read DBNAME;

for DBNAME in ${DBLIST}

pg_dump ... | gzip

man pg_dump /-Z

Зачем ; в конце команд?

Короче, все плохо.

Ты на каждую итерацию будешь новую тему создавать? Может лучше git-репозиторий себе заведешь?

MyLittleLoli ★★★★ ()
Ответ на: комментарий от MyLittleLoli

Мил человек, не сердись. То что ты пишешь хорошо, это называется оптимизация. Преждевременная оптимизация, как говорится, хуже преждевременной эякуляции.

Писать пост на каждую итерацию, если она значительная, это хорошо. Места что ли жалко?

Ты скажи может не предусмотрел чего? Вообще ЛОР по запросам некоторым в гугле не фигурирует, а мог бы. Ничего плохого в этом не вижу.

Пойду спать. Может и не буду больше писать, буду только выяснять и складывать под матрас.

Shulman ()
Ответ на: комментарий от Shulman

тем кто не имеет опыта)))

Так тут выше чётко написали. Следующий шаг - git. И нормальное описание или документация, и скрипт убери с cron. Поставь ему агрументы командной строки, сделай автономным. Для новичков бабахни примеры использования ;) Им ехать или шашечки?
Пацаны, кто немного в теме, сами с усами ;) Так что понятно - для новичков творишь.

kaban_lyalya ()

Вам в прошлый раз уже подсказали что в таком формате, ваш бекап жизнеспособен только на половину.

Ошибка - вы не выгружаете роли из базы, и работать ваш бекап будет только для пользователя постгрес.

Конструкция pg_dump | gzip избыточна, программисты уже позаботились об этом, читайте про формат -Fc

anonymous ()

Детский код какой-то. Главный косяк - вместо файла надо проверять код возврата pg_dump. Он может вылететь без вывода в stderr и твой файл backup.txt будет пустой или не перезаписан.

Bobby_ ()
Ответ на: комментарий от Bobby_

код возврата pg_dump

Как его считать? Каким должен быть код?

Вот это очень ценное замечание, главное что это уже не по оптимизации.

А код да, нагромождение копипасты. Ну почти.

Shulman ()
Ответ на: комментарий от Shulman

Но ведь на git мой скрипт никто не увидит, разве нет?

Ну, можно сообщить о скрипте на форуме (тут вроде реклама без спец. разрешения запрещена, но если скрипт бесплатный, то это же не реклама) + указать адрес в своём профиле.

Хотя этот скрипт — скорее пример, а не ПО. Его, наверно, правильнее на форуме выложить. Не представляю, как можно было бы учиться программированию или чему-то ещё, если бы во всех книжках вместо примеров hello_world и урезанных учебных конфигов давались ссылки на них на гите. :-)

aureliano15 ()
Ответ на: комментарий от Shulman

код возврата pg_dump

Как его считать? Каким должен быть код?

См., например, здесь:

Ниже приведён список определённых системных кодов возврата:

1: общие ошибки;

2: ошибки работы встроенных средств оболочки;

126: невозможно вызвать запрошенную команду;

127: команда не найдена;

128: некорректный аргумент exit;

128 + n: сигнал критической ошибки (например, kill -9 = 137);

130: скрипт прерван по Ctrl+C.

Соответственно, остальные коды возврата от 3 до 125 — на усмотрение разработчика программы, 0 — всё Ok. Ну и одновременно вывод stderr никто не мешает читать.

aureliano15 ()

За наименования файлов бэкапа вида

'daily_'$(date +%u)'_'$(date +%H)
'monthly_'$(date +%b)'_'$(date +%H)
'hot_'$(date +%Y-%b-%d-%H%M)
вроде еще никто не пинал. Так я буду первым, убейте себя ап стену.

anc ★★★★★ ()
Ответ на: комментарий от aureliano15

Минимум, а удаление старых бэкапов как делать будете? Не считая ситуации, а она может быть вполне вероятной, сегодня по какой-то причине создался бэкап с другой локалью, потом через какое-то время еще раз, так и закакать место можно. Другой вариант, оставить n последних бэкапов, сортировку по буковкам делать «не удобно».
Косяки начинаются с малого, сегодня на одно забили «не принципиально», завтра на другое «тоже не принципиально», а потом хренак - дык нас же пушистый зверек посетил. И приходиться решать, костылями через костыли и костылями погонять.

anc ★★★★★ ()
Ответ на: комментарий от MyLittleLoli

На заборе тоже написано... Если кому-то нужен «backup» как ритуальное действие, это (да и вообще что угодно) подойдёт. Иначе нужно использовать (в зависимости от цели) либо pg_basebackup, либо pg_dumpall, либо сразу сторонние решения.

Автору темы:

Вам уже вроде указывали, что pg_dump снимает далеко не всё, но Вы упорно это игнорируете, и так же упорно выкладываете скрипт на общедоступном ресурсе, создавая впечатление, что это подходит всем.

Просто для примера, попробуйте Ваш «backup» после такого:

ALTER DATABASE some_database SET default_transaction_isolation = serializable;

Вы действительно считаете, что в случае восстановления из Вашего «backup» база будет вести себя так же, как и до?

Или вот ещё, допустим, кто-то (for greater security) делает так:

DROP SCHEMA public;

Что получится после восстановления из Вашего «backup»?

anonymous ()
Ответ на: комментарий от anonymous

basebackup я уже делаю 4-ю неделю. Сервер на пострес запущен 6 недель назад. Ради одной базы каждый раз разворачивать весть кластер неохота.

Другое дело что 1С вполне достаточно такого.

У меня параллельно архивация WAL идет и pg_basebackup раз в неделю запускается. так что...

Но вы абсолютно справедливо подмечаете что этого не достаточно.

Shulman ()
Ответ на: комментарий от anonymous

А текстовый не лучше жмётся? При переходе на внешний компрессор > (xz) я так и оставил custom, а щас чё-т задумался.

Если использовать текстовый формат, то не получится воспользоваться прелестями pg_restore. Например, восстановлением одной таблицы и пр.

uspen ★★★★★ ()