LINUX.ORG.RU
ФорумAdmin

Публикую свои скрипты архивации PostgreSQL баз 1С

 ,


1

1

Внес улучшения, исправил ошибки. Мне тут говорили про какой нибудь source хостинг, но там меня никто смотреть не будет, а тут пожалуйста, любой желающий может пнуть.

Итак: для оперативного восстановления любой конкретной базы скрипт архивации на основе pg_dump. Много меня за нее пинали, но тут возникает необходимость часто восстанавливать базу с глубиной примерно в неделю. Что-то бухгалтер сломает и просит вчерашнюю базу. Восстанавливать из за нее кластер целиком вообще нет ни времени ни желания.

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

FILENAME='/root/psql_dblist'
PORT=5432
USERNAME='dbadmin'
SERVERNAME='localhost'
ARCHIVEDIR='/Backup'
SUFFIX=''
ADMINSEMAILS='your@email.ru your2@email.ru'
NETDIR='//192.168.88.11/Kamin/PostgreSQL'
EMFROM="mail@mail.su"
ERRLOG="/root/backup.txt"
EMSMTP="1.2.3.4:25"
EMPASS="Password"


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

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

if [[ 'hot' = $1 ]]
then
    SUFFIX='hot_'$(date +%Y-%m-%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 $ERRLOG 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 -Fc -f ${ARCHIVEDIR}'/'${DBNAME}'/'${DBNAME}'_'$SUFFIX'.dump.gz'
    if [[ $? -ne 0 ]]
    then
        echo $DBNAME': pg_dump error code is '$? >> $ERRLOG
    fi
done


BackupErr=$(stat $ERRLOG -c %s)

SUBJECT=''
MESSAGE=''

if [[ $BackupErr = 0 ]]
then
    SUBJECT="Archiving PostgeSQL:Ok SUFFUX=$SUFFIX"
    MESSAGE="Archiving successful. File $ERRLOG is empty."
else
    SUBJECT="PostgeSQL:NoGood SUFFUX=$SUFFIX"
    MESSAGE="File $ERRLOG 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


Естественно кластер бекапим тоже, на случай переноса или другой напасти:


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

FILENAME='/root/psql_dblist'
PORT=5432
USERNAME='dbadmin'
SERVERNAME='localhost'
ARCHIVEDIR='/Backup'
SUFFIX=''
ADMINSEMAILS='mail1@mail.ru mail2@mail.ru'
NETDIR='//192.168.88.11/Kamin/PostgreSQL'
EMFROM="mail@mail.su"
ERRLOG="/root/backup.txt"
EMSMTP="1.2.3.4:25"
EMPASS="Password"


if mount | grep -qw $NETDIR
then
    echo "Network directory is mounted"
else
    echo "Network direcrory $NETDIR is not mounted" >> $ERRLOG
    SUBJECT="PostgeSQL:NoGood pg_basebackup"
    MESSAGE="File $ERRLOG 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

pg_basebackup -h $SERVERNAME -U $USERNAME -p $PORT -w -D ${ARCHIVEDIR}'/WAL/basebackup_'$(date +%Y%m%d) -Ft
if [[ $? -ne 0 ]]
then
    echo $DBNAME': pg_basebackup error code is '$? >> $ERRLOG
fi

find ${ARCHIVEDIR}'/WAL/' -type f,d -mtime +14 -delete



BackupErr=$(stat $ERRLOG -c %s)

SUBJECT=''
MESSAGE=''

if [[ $BackupErr = 0 ]]
then
    SUBJECT="Archiving PostgeSQL:Ok  pg_basebackup"
    MESSAGE="Archiving successful. File $ERRLOG is empty."
else
    SUBJECT="PostgeSQL:NoGood  pg_basebackup"
    MESSAGE="File $ERRLOG 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


Сценарий восстановления, если будешь в неадеквате, или буду делать не я:

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

FILENAME='/root/psql_dblist'
PORT=5432
USERNAME='dbadmin'
SERVERNAME='localhost'
ARCHIVEDIR='/Backup'
SUFFIX=''
DBNAME=''
DUMPGZ=''

if [[ $1 != '' ]]
then
    DBNAME=$1
else
    echo "Point dbname as first parametr"
    exit
fi

if [[ $2 != '' ]]
then
    DUMPGZ=$2
else
    echo "Point dump.gz file as second parametr"
    exit
fi

echo $DBNAME

if psql -U $USERNAME -h $SERVERNAME -p $PORT -lqt | cut -d \| -f 1 | grep -qw $DBNAME
then
    echo "Database with this name exists on this cluster"
    exit
else
    echo -n "Create database? (Y/n) "

    read answer
    case "$answer" in
        Y) psql -U $USERNAME -h $SERVERNAME -p $PORT -c 'create database '$DBNAME -d postgres
            ;;
        *) exit 0
            ;;
    esac
fi


echo -n "Restore database? (Y/n) "

read answer
case "$answer" in
    Y)
        if file $DUMPGZ | grep -qw "PostgreSQL custom database dump"
        #/Backup/bis_kamin55_psql/bis_kamin55_psql_daily_6_08.dump.gz: PostgreSQL custom database dump - v1.12-0
        then
            pg_restore -h $SERVERNAME -U $USERNAME -p $PORT -d $DBNAME -w -Fc $DUMPGZ
        else
            gunzip < $DUMPGZ | psql -h $SERVERNAME -U $USERNAME -p $PORT -d $DBNAME
        fi
      
        ;;
    *) exit 0
        ;;
esac

Ну и в довершение, верна ли информация в crontab

# 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
0       2       *       *       5       /root/base_backup.sh 2>>/root/backup.txt


Shitcode fest.

anonymous
()

Вот такие ублюдошные конструкции

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

лучше заменить на:
[[ 'daily' = $1 ]] &&  SUFFIX='daily_'$(date +%u'_'%H)

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

Вот такие ублюдошные конструкции

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

vodz ★★★★★
()

Я так и понял, что вы ничерта даже не пробуете вникнуть что вам пишут, но зачем-то плодите топики: /root/backup.sh: строка 61: [[1: команда не найдена (комментарий)

Ну допустим, у вас такой, скорее всего выверт самообразования, когда вам зачем-то пришло в голову писать cmd ${VAR1}'/'${VAR2}. Но удивительно даже, что остальные начинают комментировать какую-то совершенно мелочную фигню, а бревна и не замечают.

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

Да, я не понял, зачем брать переменную в {}, попробовал без них и тоже все работало. Но готовое не переделывал.

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

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

Оттуда, из практики берёмся. Я и предложил заменить конструкции, где только проверка истинности выражения, без ветвления. Нафига эта куча лишних строк? Ему за них не платят, а простыню читать потом лень.

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

Да, я не понял, зачем брать переменную в {}, попробовал без них и тоже все работало.

${var} - подстановка значения переменной.

IPR ★★★★★
()
Последнее исправление: IPR (всего исправлений: 1)
Ответ на: комментарий от IPR

В общим спорить о написании одного и того же можно, это для меня полезно. Например что плохого в приведении / к строке? Я вот не знаю, надо его экранировать или так сойдет, но опыт работы с C# мне подсказывает...

В общем вы пинайте, я даже не сильно сопротивляюсь.

Но весь мой код это набор примеров от «знатоков» из разных статей по Bash, поэтому скажем так, уроки от профи просто бесценны, но нас большинство.

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

Да, я не понял, зачем брать переменную в {},

Нет, не поняли. Экранируют специальные символы, чтобы не происходило их применение по специальному назначению. А у вас всё ровно наоборот. Сами переменные могут содержать скажем символ пробела, но вы переменные при конструировании путей не экранируете. Зато экранируете самый обычный безопасный символ '/' - что просто смешно.

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

Нафига эта куча лишних строк? Ему за них не платят, а простыню читать потом лень.

У тебя перл баш головного мозга. К счастью такие динозавры с write once read never подходом довольно бодро отмирают.

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

Мне почему то тоже пришел в голову перл. Там если постараться...........

... то всё будет прекрасно

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

Да вы все упоролись. Что плохого в конструкции:

[ условие ] && команда

Зачем эти бессмысленные if/then/fi, если нет else/elif?

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

Да ты упоролся. Что плохого писать в одну строку? Зачем эти бессмысленные переносы строк/структуризация кода если можно свалить все в кашу?

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

Не оправдываю bash и его странных поклонников, но вообще в таких случаях нормально писать в одну строку, если в языке для этого есть упрощённый синтаксис (как в Java, например).

anonymous
()

Ты забыла

Упомянуть.

mos ★★☆☆☆
()
Ответ на: комментарий от shell-script

Это будет ещё лучше, не спорю.

IPR ★★★★★
()

Про экранирование тебе уже сказали выше.

В третьем скрипте проверка аргументов коммандной строки никакой пользы не даёт, потому как по сути ничего не проверяет. Вопросы Y/N бесполезны, потому как нет конкретики какую именно бд ты там сейчас собрался создавать/восстанавливать, так что в нынешнем виде тоже можно выкинуть(или переписать).

Ну и в целом какой-то бардак. В одном скрипте параметры одним способом принимаются, в другом - другим. Вместо того, чтобы отлавливать сообщения об ошибках, в логах пустые коды - причём не факт, что именно от базы. Да и логи так, для галочки(как проверки выше), потому как вне зависимости от ошибки, ты в итоге делаешь exit.

Плохо всё.

shell-script ★★★★★
()
Ответ на: комментарий от entefeed

Да ты упоролся. Что плохого писать в одну строку? Зачем эти бессмысленные переносы строк/структуризация кода если можно свалить все в кашу?

Нет ты. Нафиг размазывать на три строки проверку условия? Естественно, если есть ветвления это имеет смысл, но тут-то зачем? Что выглядит выразительнее и понятнее?:

[ -w /etc/rc.conf ] && ee /etc/rc.conf

или
if [ -w /etc/rc.conf ] ; then
   ee /etc/rc.conf
fi

IPR ★★★★★
()
Ответ на: комментарий от shell-script

Вопросы Y/N бесполезны, потому как нет конкретики какую именно бд ты там сейчас собрался создавать/восстанавливать, так что в нынешнем виде тоже можно выкинуть(или переписать).

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

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

Надо давать имя базы в вопросе. Если кто-то в параметре написал имя, он на вопрос о подтверждении автоматом согласится.

Про параметры я уже написал, их надо проверять. script.sh foo_base bar.gz в твоём варианте валидная ситуация, даже если в bar.gz лежит архив с порнухой.

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

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

Shulman
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.