Содержание
Хранилище файлов NFS, без встроенного почтового сервера
Краткое описание
Скрипты основаны на инструкциях по установке Корпоративный сервер 2024 в архитектуре middle
Для работы скриптов необходимо наличие установленного rsync на серверах участвующих в схеме КС и с которого запускается скрипт. На сервере, с которого запускается скрипт, необходимо установить lbzip2 (в скрипте есть проверка).
Скрипт копирует и архивирует информацию из папок
Сервер с ролью Диск
/etc/supervisor (в REDOS /etc/supervisor.d)
/opt/r7-office
/var/r7-office
/var/www/r7-office
Сервер с ролью Сервер документов
/etc/r7-office
/var/www/r7-office
Сервер с ролью Поиск
/opt/r7-office
/var/r7-office
/etc/supervisor (в REDOS /etc/supervisor.d)
Сервер с ролью NFS
/mnt/nfs
Перед запуском необходимо вписать следующую информацию
- Если для доступа к серверам используется достпуп по ключу, вписать путь.
- Если доступ без ключа, тогда нужно изменить команды доступа у rsync и ssh.
- Если для доступа по ssh используется нестандартный порт, так же нужно указать в командах.
- Нужно ввести адреса серверов согласно их ролям.
Описание переменных
Переменная | Описание |
BACKUP_DIR= | Папка для хранения архивов |
BACKUP_DATE=$(date + ‘%Y-%m-%d’) | Формат даты для имени архива |
SSH_KEY_PATH= | Путь к SSH ключу |
SSH_PORT=22 | SSH порт по которму осуществляется подключение к серверам |
NUM_CORES=$(($(nproc)/2)) | Для работы архиватора по-умолчанию берется половина ядер на сервере бэкапа |
DS_IP=172.16.10.11 | Адрес сервера с ролью Сервер документов |
KS_IP=172.16.10.12 | Адрес сервера с ролью Диск |
SRCH_IP=172.16.10.13 | Адрес сервера с ролью Поиск |
NFS_IP=172.16.10.14 | Адрес сервера с ролью NFS |
BACKUP_FILE | Имя файла с архивом для восстановления |
Список переменных с адресами серверов вынесен в отдельный файл backup.conf
#BACKUP_FILE="cddisk-2024-04-23.tar.bz2" #Только для восстановления данных из архива BACKUP_DIR="backup/corpportal" BACKUP_DATE=$(date +'%Y-%m-%d') SSH_KEY_PATH="backup/id_rsa" SSH_PORT=22 NUM_CORES=$(( ($(nproc) + 1) / 2 )) DS_IP="172.16.10.11" KS_IP="172.16.10.12" SRCH_IP="172.16.10.13" NFS_IP="172.16.10.14" LOG_FILE="$BACKUP_DIR/backup_${BACKUP_DATE}.log" #Имя файла содержит дату
Пример скрипта для создания резервной копии
#!/bin/bash # Путь до файла конфигурации source backup.conf # Вызов функции cleanup после выполнения прерывания trap cleanup INT TERM trap cleanup_exit EXIT # Одновременный вывод в консоль и в лог файл #exec > >(tee -a "$LOG_FILE") 2>&1 cleanup() { log_info "Завершение скрипта после прерывания..." # Добавить что то если нужно exit 1 } cleanup_exit() { log_info "Завершение скрипта..." # Добавить что то если нужно exit 1 } # Функции логирования log_info() { echo "$(date +'%Y-%m-%d %H:%M:%S') INFO: $1" | tee -a "$LOG_FILE" } log_warn() { echo "$(date +'%Y-%m-%d %H:%M:%S') WARN: $1" | tee -a "$LOG_FILE" } log_error() { echo "$(date +'%Y-%m-%d %H:%M:%S') ERROR: $1" | tee -a "$LOG_FILE" } # Создаем backup каталог mkdir -p "$BACKUP_DIR" # Проверка, установлен ли lbzip2 и rsync if ! command -v lbzip2 &> /dev/null; then log_error "Ошибка: lbzip2 не установлен. Установите lbzip2 и повторите попытку." exit 1 fi if ! command -v rsync &> /dev/null; then log_error "Ошибка: rsync не установлен. Установите rsync и повторите попытку." exit 1 fi # Функция для получения пути до директории supervisor get_supervisor_dir() { local server=$1 local supervisor_dir="" # Проверяем наличие каталогов в порядке приоритета if ssh -i "$SSH_KEY_PATH" -p "$SSH_PORT" root@"$server" "test -d /etc/supervisord.d" 2>/dev/null; then supervisor_dir="/etc/supervisord.d" elif ssh -i "$SSH_KEY_PATH" -p "$SSH_PORT" root@"$server" "test -d /etc/supervisor" 2>/dev/null; then supervisor_dir="/etc/supervisor" else log_error "Не найден каталог supervisor на сервере $server" return 1 fi #log_info "На сервере $server путь до supervisor $supervisor_dir" echo $supervisor_dir return 0 } get_databases(){ scp -i "$SSH_KEY_PATH" -P "$SSH_PORT" root@"$KS_IP":/opt/r7-office/Api/appsettings.json . # Проверка кода выхода SCP_EXIT_STATUS=$? # Обработка результата if [ $SCP_EXIT_STATUS -eq 0 ]; then log_info "Файл конфигурации удалось скопировать" else log_error "Файл конфигурации не удалось скопировать" exit 1 # Завершаем скрипт с ошибкой fi # Данные для авторизации в PostgreSQL DB_PATH_PARAM=./appsettings.json PSQL_HOST=$(grep -oP "Host=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2); PSQL_DB_NAME=$(grep -oP "Database=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2); PSQL_USER=$(grep -oP "Username=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2); PSQL_PASS=$(grep -oP "Password=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2); PSQL_PORT=$(grep -oP "Port=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2); export PGPASSWORD=$PSQL_PASS PSQL="psql -b -h$PSQL_HOST -p$PSQL_PORT -d$PSQL_DB_NAME -U$PSQL_USER" echo "DB_HOST=$PSQL_HOST" echo "DB_PORT=$PSQL_PORT" echo "DB_NAME=$PSQL_DB_NAME" echo "DB_USER=$PSQL_USER" echo "PSQL=$PSQL" # Удалить файл конфигурации rm -rf $DB_PATH_PARAM # Очистка от старых дампов rm -rf $BACKUP_DIR/cddisk_db_*.tar.gz local db_backup_file="$BACKUP_DIR/cddisk_db_$BACKUP_DATE.tar.gz" pg_dump -v -h $PSQL_HOST -U $PSQL_USER -d $PSQL_DB_NAME -F c -c -f "$db_backup_file" if [ $? -eq 0 ]; then log_info "Бэкап успешно создан" else log_error "Бэкап создан с ошибкой" exit 1 # Завершаем скрипт с ошибкой fi } # Время начала создания бэкапа START_BACKUP_TIME=$(date +'%Y-%m-%d %H:%M:%S') log_info "Начало резервного копирования: $START_BACKUP_TIME" # Получить каталоги supervisor KS_SUPERVISOR_DIR=$(get_supervisor_dir $KS_IP) SRCH_SUPERVISOR_DIR=$(get_supervisor_dir $SRCH_IP) mkdir -p $BACKUP_DIR/ds/etc/r7-office mkdir -p $BACKUP_DIR/ds/var/www/r7-office mkdir -p $BACKUP_DIR/ks/$KS_SUPERVISOR_DIR mkdir -p $BACKUP_DIR/ks/opt/r7-office mkdir -p $BACKUP_DIR/ks/var/r7-office mkdir -p $BACKUP_DIR/ks/var/www/r7-office mkdir -p $BACKUP_DIR/srch/opt/r7-office mkdir -p $BACKUP_DIR/srch/$SRCH_SUPERVISOR_DIR mkdir -p $BACKUP_DIR/srch/var/r7-office mkdir -p $BACKUP_DIR/nfs/mnt/ rsync_msg(){ code_err=$1 host_ip=$2 # Проверяем код возврата if [ $code_err -eq 23 ]; then log_error "Ошибка: rsync не установлен или произошла другая фатальная ошибка на удаленном хосте $host_ip. (code 23). Проверьте установку rsync или настройки сети." exit 1 elif [ $code_err -ne 0 ]; then log_error "Ошибка rsync (code $code_err) при копировании с $host_ip. Смотрите лог: $LOG_FILE" exit 1 fi log_info "Копирование с $host_ip завершено успешно." } # Получить дамп базы get_databases # RSYNC копирование данных с удаленный серверов log_info "Начало копирования с сервера $DS_IP из каталога /etc/r7-office" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$DS_IP:/etc/r7-office $BACKUP_DIR/ds/etc/r7-office/ rsync_msg $? $DS_IP log_info "Начало копирования с сервера $DS_IP из каталога /var/www/r7-office" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$DS_IP:/var/www/r7-office $BACKUP_DIR/ds/var/www/r7-office/ rsync_msg $? $DS_IP log_info "Начало копирования с сервера $KS_IP из каталога $KS_SUPERVISOR_DIR" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$KS_IP:$KS_SUPERVISOR_DIR $BACKUP_DIR/ks/$KS_SUPERVISOR_DIR/ rsync_msg $? $KS_IP log_info "Начало копирования с сервера $KS_IP из каталога /opt/r7-office" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$KS_IP:/opt/r7-office $BACKUP_DIR/ks/opt/r7-office/ rsync_msg $? $KS_IP log_info "Начало копирования с сервера $KS_IP из каталога /var/r7-office" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$KS_IP:/var/r7-office $BACKUP_DIR/ks/var/r7-office/ rsync_msg $? $KS_IP log_info "Начало копирования с сервера $KS_IP из каталога /var/www/r7-office" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$KS_IP:/var/www/r7-office $BACKUP_DIR/ks/var/www/r7-office/ rsync_msg $? $KS_IP log_info "Начало копирования с сервера $SRCH_IP из каталога /opt/r7-office" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$SRCH_IP:/opt/r7-office $BACKUP_DIR/srch/opt/r7-office/ rsync_msg $? $SRCH_IP log_info "Начало копирования с сервера $SRCH_IP из каталога $SRCH_SUPERVISOR_DIR" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$SRCH_IP:$SRCH_SUPERVISOR_DIR $BACKUP_DIR/srch/$SRCH_SUPERVISOR_DIR/ rsync_msg $? $SRCH_IP log_info "Начало копирования с сервера $SRCH_IP из каталога /var/r7-office" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$SRCH_IP:/var/r7-office $BACKUP_DIR/srch/var/r7-office/ rsync_msg $? $SRCH_IP log_info "Начало копирования с сервера $NFS_IP из каталога /mnt/nfs" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" root@$NFS_IP:/mnt/ $BACKUP_DIR/nfs/mnt/ rsync_msg $? $NFS_IP # Создание архива с бэкапом BACKUP_DATE=$(date +'%Y-%m-%d %H:%M:%S') log_info "Формируется архив..." tar cvf "$BACKUP_DIR/cddisk-${BACKUP_DATE}.tar.bz2" --selinux --use-compress-prog="lbzip2 -k -n$NUM_CORES" $BACKUP_DIR/ds/etc/r7-office $BACKUP_DIR/ds/var/www/r7-office $BACKUP_DIR/ks/$KS_SUPERVISOR_DIR $BACKUP_DIR/ks/opt/r7-office $BACKUP_DIR/ks/var/r7-office $BACKUP_DIR/ks/var/www/r7-office $BACKUP_DIR/srch/opt/r7-office $BACKUP_DIR/srch/$SRCH_SUPERVISOR_DIR $BACKUP_DIR/srch/var/r7-office $BACKUP_DIR/nfs/mnt/nfs $db_backup_file if [ $? -eq 0 ]; then log_info "Архив успешно создан" else log_error "Архив создан с ошибкой" exit 1 # Завершаем скрипт с ошибкой fi # Время завершения бекапирования END_BACKUP_TIME=$(date +'%Y-%m-%d %H:%M:%S') log_info "Завершение резервного копирования: $end_time" # Время в секундах работы бекапирования START_TIMESTAMP=$(date -d "$START_BACKUP_TIME" +%s) END_TIMESTAMP=$(date -d "$END_BACKUP_TIME" +%s) TOTAL_DURATION=$((END_TIMESTAMP - START_TIMESTAMP)) log_info "Общее время выполнения: $TOTAL_DURATION секунд" log_info "Завершение резервного копирования: $(date +'%Y-%m-%d %H:%M:%S')"
Восстановление из архива
Обратите внимание, если при восстановлении изменились адреса серверов внутри архитектуры, возможны ошибки в работе Корпоративного сервера. Нужно будет проверить все настройки, связанные с этими серверами согласно инструкции по установке.
Пример скрипта восстановления
#!/bin/bash # Путь до файла конфигурации source restore.conf # Функция для обработки прерываний trap cleanup INT TERM trap cleanup_exit EXIT # Функции для логирования log_info() { echo "$(date +'%Y-%m-%d %H:%M:%S') INFO: \$1" | tee -a "$LOG_FILE" } log_warn() { echo "$(date +'%Y-%m-%d %H:%M:%S') WARN: \$1" | tee -a "$LOG_FILE" } log_error() { echo "$(date +'%Y-%m-%d %H:%M:%S') ERROR: \$1" | tee -a "$LOG_FILE" } # Функция очистки при прерывании cleanup() { log_info "Скрипт восстановления прерван. Выполняется очистка..." # Добавьте дополнительные шаги очистки, если необходимо exit 1 } # Функция очистки при выходе cleanup_exit() { log_info "Скрипт восстановления завершает работу." # Добавьте дополнительные шаги очистки, если необходимо exit 1 } # Проверка наличия необходимых команд if ! command -v lbzip2 &> /dev/null; then log_error "Ошибка: lbzip2 не установлен. Установите lbzip2 и повторите попытку." exit 1 fi if ! command -v rsync &> /dev/null; then log_error "Ошибка: rsync не установлен. Установите rsync и повторите попытку." exit 1 fi if ! command -v psql &> /dev/null; then log_error "Ошибка: psql не установлен. Установите psql и повторите попытку." exit 1 fi # Функция для получения пути до директории supervisor get_supervisor_dir() { local server=\$1 local supervisor_dir="" if ssh -i "$SSH_KEY_PATH" -p "$SSH_PORT" root@"$server" "test -d /etc/supervisord.d" 2>/dev/null; then supervisor_dir="/etc/supervisord.d" elif ssh -i "$SSH_KEY_PATH" -p "$SSH_PORT" root@"$server" "test -d /etc/supervisor" 2>/dev/null; then supervisor_dir="/etc/supervisor" else log_error "Не найден каталог supervisor на сервере $server" return 1 fi echo "$supervisor_dir" return 0 } # Функция для восстановления баз данных restore_databases() { # Копируем файл конфигурации appsettings.json из резервной копии scp -i "$SSH_KEY_PATH" -P "$SSH_PORT" root@"$KS_IP":"$BACKUP_DIR/ks/opt/r7-office/appsettings.json" . SCP_EXIT_STATUS=$? if [ $SCP_EXIT_STATUS -eq 0 ]; then log_info "Файл конфигурации успешно скопирован." else log_error "Не удалось скопировать файл конфигурации." exit 1 fi # Извлекаем параметры для подключения к PostgreSQL DB_PATH_PARAM=./appsettings.json PSQL_HOST=$(grep -oP "Host=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2) PSQL_DB_NAME=$(grep -oP "Database=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2) PSQL_USER=$(grep -oP "Username=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2) PSQL_PASS=$(grep -oP "Password=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2) PSQL_PORT=$(grep -oP "Port=[^\";]*" $DB_PATH_PARAM | head -1 | cut -d'=' -f2) export PGPASSWORD=$PSQL_PASS PSQL="psql -h $PSQL_HOST -p $PSQL_PORT -U $PSQL_USER -d postgres" # Проверяем существование базы данных DATABASE_EXISTS=$($PSQL -tc "SELECT 1 FROM pg_database WHERE datname = '$PSQL_DB_NAME';") if [ -z "$DATABASE_EXISTS" ]; then # База данных не существует, создаем её log_info "База данных $PSQL_DB_NAME не существует. Создание новой базы данных." $PSQL -c "CREATE DATABASE $PSQL_DB_NAME;" if [ $? -eq 0 ]; then log_info "База данных $PSQL_DB_NAME успешно создана." else log_error "Не удалось создать базу данных $PSQL_DB_NAME." exit 1 fi else # База данных существует, удаляем её перед восстановлением log_info "База данных $PSQL_DB_NAME существует. Удаление существующей базы данных." $PSQL -c "DROP DATABASE IF EXISTS $PSQL_DB_NAME;" if [ $? -eq 0 ]; then log_info "Существующая база данных $PSQL_DB_NAME успешно удалена." else log_error "Не удалось удалить существующую базу данных $PSQL_DB_NAME." exit 1 fi # Создаем новую базу данных $PSQL -c "CREATE DATABASE $PSQL_DB_NAME;" if [ $? -eq 0 ]; then log_info "Новая база данных $PSQL_DB_NAME успешно создана." else log_error "Не удалось создать новую базу данных $PSQL_DB_NAME." exit 1 fi fi # Восстанавливаем базу данных из резервной копии pg_restore -h $PSQL_HOST -p $PSQL_PORT -U $PSQL_USER -d $PSQL_DB_NAME -v "$BACKUP_DIR/cddisk_db_$BACKUP_DATE.tar.gz" if [ $? -eq 0 ]; then log_info "База данных $PSQL_DB_NAME успешно восстановлена." else log_error "Не удалось восстановить базу данных $PSQL_DB_NAME." exit 1 fi # Удаляем файл конфигурации rm -f $DB_PATH_PARAM } # Начало процесса восстановления START_RESTORE_TIME=$(date +'%Y-%m-%d %H:%M:%S') log_info "Начало процесса восстановления: $START_RESTORE_TIME" # Восстановление баз данных restore_databases # Восстановление данных с помощью rsync log_info "Начало восстановления данных с резервной копии на серверы." # Восстановление данных на сервер DS log_info "Восстановление /etc/r7-office на $DS_IP" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/ds/etc/r7-office/ root@$DS_IP:/etc/r7-office/ rsync_msg $? $DS_IP log_info "Восстановление /var/www/r7-office на $DS_IP" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/ds/var/www/r7-office/ root@$DS_IP:/var/www/r7-office/ rsync_msg $? $DS_IP # Восстановление данных на сервер KS log_info "Восстановление директории supervisor на $KS_IP" KS_SUPERVISOR_DIR=$(get_supervisor_dir $KS_IP) rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/ks/$KS_SUPERVISOR_DIR/ root@$KS_IP:$KS_SUPERVISOR_DIR/ rsync_msg $? $KS_IP log_info "Восстановление /opt/r7-office на $KS_IP" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/ks/opt/r7-office/ root@$KS_IP:/opt/r7-office/ rsync_msg $? $KS_IP log_info "Восстановление /var/r7-office на $KS_IP" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/ks/var/r7-office/ root@$KS_IP:/var/r7-office/ rsync_msg $? $KS_IP log_info "Восстановление /var/www/r7-office на $KS_IP" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/ks/var/www/r7-office/ root@$KS_IP:/var/www/r7-office/ rsync_msg $? $KS_IP # Восстановление данных на сервер SRCH log_info "Восстановление директории supervisor на $SRCH_IP" SRCH_SUPERVISOR_DIR=$(get_supervisor_dir $SRCH_IP) rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/srch/$SRCH_SUPERVISOR_DIR/ root@$SRCH_IP:$SRCH_SUPERVISOR_DIR/ rsync_msg $? $SRCH_IP log_info "Восстановление /opt/r7-office на $SRCH_IP" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/srch/opt/r7-office/ root@$SRCH_IP:/opt/r7-office/ rsync_msg $? $SRCH_IP log_info "Восстановление /var/r7-office на $SRCH_IP" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/srch/var/r7-office/ root@$SRCH_IP:/var/r7-office/ rsync_msg $? $SRCH_IP # Восстановление данных NFS log_info "Восстановление данных NFS на $NFS_IP" rsync -avz --partial -e "ssh -i $SSH_KEY_PATH -p $SSH_PORT" --log-file="$LOG_FILE" $BACKUP_DIR/nfs/mnt/ root@$NFS_IP:/mnt/ rsync_msg $? $NFS_IP # Завершение процесса восстановления END_RESTORE_TIME=$(date +'%Y-%m-%d %H:%M:%S') log_info "Процесс восстановления завершен: $END_RESTORE_TIME" # Рассчитываем общее время выполнения START_TIMESTAMP=$(date -d "$START_RESTORE_TIME" +%s) END_TIMESTAMP=$(date -d "$END_RESTORE_TIME" +%s) TOTAL_DURATION=$((END_TIMESTAMP - START_TIMESTAMP)) log_info "Общее время выполнения: $TOTAL_DURATION секунд"