Итак, я написал короткий сценарий, который я планирую запускать через задание cron ежедневно, чтобы упаковать файлы моего сайта и отправить их в удаленное место. Я также планирую добавить дампы БД, но я еще не дошел до этого.
Однако моя проблема сегодня заключается в том, что я не уверен, как регистрировать вывод каждой команды для ошибок, предупреждений или другой соответствующей информации, которую может выводить команда. Я также хотел бы установить какой-нибудь тип отказоустойчивости, чтобы, если что-то пойдет не так, скрипт остановится на своем пути и уведомит меня по электронной почте или что-то в этом роде. Хорошо, электронная почта не так важна, но было бы неплохо.
У кого-нибудь есть идеи на этот счет? Вот что у меня есть на данный момент.
Кстати, оба сервера - CentOS 6.2, работающие под стандартной LAMP.
#!/bin/sh
#################################
### Set Vars
#################################
THEDATE=`date +%m%d%y%H%M`
#################################
### Create Archives
#################################
tar -cf /root/backups/files/server_BAK_${THEDATE}.tar -C / var/www/vhosts
gzip /root/backups/files/server_BAK_${THEDATE}.tar
#################################
### Send Data to Remote Server
#################################
scp /root/backups/files/server_BAK_${THEDATE}.tar.gz user@host:/home/bak1/ftp/backups/
#################################
### Remove Data from this Server
#################################
rm -rf /root/backups/files/server_BAK_${THEDATE}.tar.gz
Вы можете перенаправить ошибку для каждой команды в конкретный файл.
grep da * 2> grep-errors.txt
Это перенаправляет ошибки из файла grep в файл grep-errors.txt.
grep da * 1>&2
Это приведет к тому, что стандартный вывод программы будет записан в тот же файловый дескриптор, что и стандартный вывод.
rm -rf * 2>&1
Это приведет к тому, что стандартный вывод программы будет записан в тот же файловый дескриптор, что и стандартный вывод.
rm -f $(find / -name core) &> /dev/null
Это поместит каждый вывод программы в файл. Иногда это подходит для записей cron, если вы хотите, чтобы команда проходила в абсолютной тишине. Конечно, вы можете заменить / dev / null каким-нибудь файлом и записать в него весь вывод.
Это для регистрации ошибок. Я знаю, что это простой сценарий резервного копирования, но вы снова пытаетесь изобрести колесо. И, на мой взгляд, вам стоит проверить Bacula. Это довольно большое решение для резервного копирования только одного сервера, но оно сделает все, что вы запрашиваете. Buckup, уведомлять и т. Д. И многое другое. У вас будет одно из лучших решений для резервного копирования. Настроить его только для одного или нескольких серверов довольно просто, и вы сделаете это за несколько часов.
Если вы все еще хотите использовать свой скрипт, вам следует перенаправить все ошибки на stdout после добавления этого скрипта в cron, он будет отправлять вам по электронной почте каждый вывод этого скрипта. Вы должны проверять только / etc / aliases для корневой записи и писать туда свою почту следующим образом:
root: your@mail.com
Я внес некоторые изменения в сценарий. Вот новый. Все еще работаю над этим,
РЕДАКТИРОВАТЬ: Поэтому я внес в сценарий еще больше изменений, чтобы включить повторное резервное копирование баз данных. Ниже самая последняя версия. Сейчас я его тестирую.
Мои новые вопросы таковы: я не хочу показывать пароли для базы данных в файле журнала, поэтому я установил первый «набор» на «set -eu». Но я решил, что хочу посмотреть, какие команды выполняются в сценарии в файле журнала, поэтому после завершения итерации БД и дампа я сбрасываю "set" на "set -eux". Это хорошая практика, что я сделал? Кроме того, как я могу показать отметки времени в файле журнала?
#/bin/sh
#################################
### Set Vars
#################################
LOCALBAKTMP='/root/backups/files' ###~~~PLACE WHERE TMP FILES GO
LOCALBAKLOC='var/www/vhosts' ###~~~DIRECTORY TO BACKUP (NO SLASH IN FRONT)
REMOTEUSR='user' ###~~~USER AT REMOTE SERVER
REMOTEHOST='host' ###~~~REMOTE HOST ADDRESS
REMOTEDEST='/home/bak1/ftp/backups/' ###~~~FILE DESTINATION AT REMOTE
LOGDIR='/root/backups/logs/' ###~~~LOCAL BACKUP LOG DIRECTORY
DELLOGSDAYS='30' ###~~~DAYS TO STORE LOG FILES
THEDATE=`date +%m%d%y%H%M` ###~~~DATE VARIABLE
DB_BACKUP="/root/backups/files/dbs" ###~~~DB BACKUP LOCATION
LOCALDBLOC="root/backups/files/dbs" ###~~~DB FILES TO BAK
DB_USER="dbuser" ###~~~DB ROOT USER
DB_PASSWD="dbpassword" ###~~~DB ROOT PASS
HN=`hostname | awk -F. '{print $1}'` ###~~~DO NOT CHANGE
#################################
### Set Logging
#################################
trap error_handler ERR
exec &> ${LOGDIR}bak_${THEDATE}.log
set -eu
#################################
### Dump MySQL
#################################
for db in $(mysql --user=$DB_USER --password=$DB_PASSWD -e 'show databases' -s --skip-column-names|grep -vi information_schema);
do mysqldump --user=$DB_USER --password=$DB_PASSWD --opt $db | gzip > "$DB_BACKUP/mysqldump-$HN-$db-$(date +%Y-%m-%d).sql.gz";
done
#Log commands for the rest of the script
set -eux
#################################
### Create Archives
#################################
tar -cf ${LOCALBAKTMP}/server_BAK_${THEDATE}.tar -C / ${LOCALBAKLOC}
gzip ${LOCALBAKTMP}/server_BAK_${THEDATE}.tar
tar -cf ${LOCALBAKTMP}/db_BAK_${THEDATE}.tar -C / ${LOCALDBLOC}
gzip ${LOCALBAKTMP}/db_BAK_${THEDATE}.tar
tar -cfz full_BAK_${THEDATE}.tar.gz *_BAK_${THEDATE}.tar.gz
#################################
### Send Data to Remote Server
#################################
scp ${LOCALBAKTMP}/full_BAK_${THEDATE}.tar.gz ${REMOTEUSR}@${REMOTEHOST}:${REMOTEDEST}
#################################
### Remove Data from this Server
#################################
rm -f ${LOCALBAKTMP}/*_BAK_${THEDATE}.tar.gz
rm -rf ${DB_BACKUP}/*.sql.gz
find ${LOGDIR}* -mtime +${DELLOGSDAYS} -exec rm {} \;
Немного неорганизованный ответ, но, пожалуйста, прочтите его.
Чтобы ваш скрипт останавливался на своем пути при возникновении какой-либо ошибки:
set -e
Это гарантирует, что если любой ваших команд не удастся, скрипт тут же завершится ошибкой. Другие хорошие идеи:
function error_handler() {
# This will get run when an error is detected
}
trap error_handler ERR
Это запустит error_handler
когда команда не работает. Вы также можете иметь EXIT
обработчик для запуска кода каждый раз при выходе из вашего скрипта.
Чтобы записать весь вывод вашего скрипта в файл:
exec &> some_log_file
Чтобы также иметь возможность видеть команды, которые выполняет ваш скрипт, в файле журнала (отлично подходит для устранения неполадок):
set -x
Чтобы ваш скрипт выдавал предупреждения о неопределенных переменных:
set -u
Подводя итог, начните свой скрипт с:
trap error_handler ERR
exec &> some_log_file
set -eux
Если вы запускаете скрипт из cron, он отправит вам электронное письмо, если будет какой-либо вывод из вашего скрипта. Чтобы получать электронное письмо только при возникновении проблемы, поставьте cat some_log_file
в обработчике ошибок, и все готово.
Обновить: Чтобы ответить на другие ваши вопросы.
if
заявление. подобно if ! <some command>; then <what do you do if it fails, or possibly nothing>; fi
trap error_handler
вам также необходимо определить function error_handler
.set -eu
и set -eux
неплохая идея, но ...... если вы беспокоитесь о безопасности, вы не должны помещать пароль mysql в командную строку (любой, кто запускает pgrep -lf mysql
увидим это). Вместо этого используйте файл опций. И тогда вам не нужно беспокоиться о паролях в файлах журнала.
option_file=`mktemp`
cat > $option_file <<EOF
[client]
password = $DB_PASSWD
user = $DB_USER
EOF
А потом беги mysqldump
с участием --default-extra-path=$option_file
. И не забудьте удалить $option_file
когда он тебе больше не нужен.
rsync
вместо того scp
. Он работает намного лучше для копирования относительно больших файлов.