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 ☆
() автор топика
Вы не можете добавлять комментарии в эту тему: топик перемещен в архив.