Резервное копирование баз программы «1С: Предприятие» различных версий

22 апреля 2011 г.

Возникла следующая задача: есть сервер на Alt Linux на нем установлены различные варианты 1С.
Все базы можно свести к 3 вариантам:

  • файловые версии баз причем как 7-ки так и 8-ки (тут все просто, копируем папки)
  • базы 7-ки, хранящиеся в PostgreSQL (тут нужен дамп базы, но иногда желательно и папку с конфигурацией, отчетами и т.д. тоже копировать)
  • клиент-серверная 8-ка с хранением в PostgreSQL (тут в принципе хватит просто дампа базы)

Конечно у 1С есть свои средства резервного копирования, но все таки ИМХО было быстрее написать единый скрипт, чем копаться сначала в 7-ке, потом в 8-ке, чтобы в итоге это все работало. Поэтому решено написать свой скрипт, который будет все это копировать и выстроит приемлимую структуру копий.

Для бэкапа всего этого зоопарка была выбрана следующая структура хранения данных:

Папка с копиями — версия программы — имя базы — архив от определенного числа.


Также, на всякий случай, ежемесячно откладывать в отдельную папку по резервной копии.
В итоге работы появился bash-скрипт, о котором речь и пойдет под катом.

Решено использовать файл конфигурации, в котором описаны базы в следующем виде:

Имя базы: путь относительно общего каталога с базами: тип базы: имя
базы в PostgreSQL

В принципе, я думаю тут все ясно, остановлюсь только на 3-х моментах:
В результате получается файл содержащий примерно следующее
Base1:cat1/base1:f
Base2:cat2/base2:s:base_2
#Base3:base3:f
Base4::8:Base4

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

Перейдем теперь к самому скрипту. Он разбит на 3 части:

  • Ввод переменных
  • Копирование во временную папку
  • Архивирование и перенос в папку с бэкапами

В принципе, я думаю комментариев в нем достаточно да и сам он не особо сложен.

#!/bin/bash
# Переменные
pathtmp='путь к временной папке'
pathfrom='путь к папке с базами'
pathto='путь к папке с бэкапами'
format=$(date +%Y%m%d) # дата в виде годмесяцчисло
cfg="путь к конфигу"

# Параметры подключения к Postgre (если необходимо)
dbhost='адрес сервера'
dbuser='имя_пользователя'
dbpass='пароль'

# функция чтения переменных из строчки
set_conf_var () {
mark=0 #маркер, определяющий тип резервного копирования
if [ "$1" != "" ] # отделяем закомментированые базы
then
folderto=$(head -${cont} $cfg | tail -1|cut -f1 -d:)
folderfrom=$(head -${cont} $cfg | tail -1|cut -f2 -d:)
type=$(head -${cont} $cfg | tail -1|cut -f3 -d:)
mark=1
else
mark=0
fi
if [ "$type" == "s" ]
then
sql_base=$(head -${cont} $cfg | tail -1|cut -f4 -d:)
ver='77' # переменная с версией программы 1С
mark=3
#Это условие нужно для того чтобы раз в неделю и в начале месяца к дампу добавлялась папка с конфигурацией
if [ "$(date +%a)" == 'Thu' ]||[ "$(date +%a)" == 'Чтв' ]||[ "$(date +%d)" == '01' ]; then mark=2; fi
fi
if [ "$type" == "8" ]; then sql_base=$(head -${cont} $cfg | tail -1|cut -f4 -d:);mark=3; ver='82'; fi
# тут мы определяем какая именно из файловых версий лежит 7-ая или 8-ая версия
if [ "$type" == "f" ]
then
v77=$(ls "${pathfrom}${folderfrom}/" | grep -ic 1cv7.md)
v82=$(ls "${pathfrom}${folderfrom}/" | grep -ic 1cv8.1cd)
if [ $v77 -ge 1 ]; then ver='77'; else if [ $v82 -ge 1 ]; then ver='82'; fi; fi
echo $v77, $v82, $1
fi
}

# функция копирования исходных данных во временную папку
copy_src () {
# копируем только файлы
if [ $1 -eq 1 ]
then
rsync -r "${pathfrom}${folderfrom}/" $format
fi
#копируем файлы и делаем дамп
if [ $1 -eq 2 ]
then
rsync -r "${pathfrom}${folderfrom}/" $format
export PGPASSWORD=${dbpass}
pg_dump -h $dbhost -U $dbuser -c $sql_base>"${format}/base_dump.sql"
export PGPASSWORD=
fi
# только дамп базы
if [ $1 -eq 3 ]
then
export PGPASSWORD=${dbpass}
pg_dump -h $dbhost -U $dbuser -c $sql_base>"${format}/base_dump.sql"
export PGPASSWORD=
fi
}

# Проверка на наличие конфига
if [ -f $cfg ]; then : ; else echo "Нет файла конфигурации" exit 0; fi
# Подсчет общего количества баз (использовал для отладки, можно закомментить или использовать в логах)
cont=1
cfg_all=$(cat "$cfg"|grep -c ".")
cfg_comment=$(cat "$cfg" |grep -c \#)
echo $cfg_all,$cfg_comment
let $[bases_cont=$cfg_all - $cfg_comment]
echo "Всего: $bases_cont баз(ы)"

# Подготовка папок для бэкапа
# создаем (если нет) папку 1cbackup
if [ -d "${pathtmp}/1cbackup" ]; then : ; else mkdir "${pathtmp}/1cbackup"; fi
# читаем построчно файл конфигурации
until [ $cont -gt $cfg_all ]
do
string=$(head -${cont} $cfg | tail -1|cut -f1 -d\#)
set_conf_var "$string"

if [ $mark -ne 0 ]
then
cd ${pathtmp}/1cbackup/
# в одной временной директории создается еще одна, сделано на всякий случай, если вдруг пойдет что то не так собирать файлы придется не по всему темпу а в одной папке (лично мне так удобней)
mkdir $format
copy_src "$mark"
# проверяем существует ли папка для бэкапа
if [ -d "${pathto}${ver}/${folderto}" ]; then : ; else mkdir "${pathto}/${ver}/${folderto}"; fi

cd $format
# проверка на начало месяца, в начале месяца откладываем отдельно
if [ "$(date +%d)" == '01' ]
then
tar -czf "${pathto}${ver}/${folderto}/monthly/${format}.tar.gz" *
else
tar -czf "${pathto}${ver}/${folderto}/${format}.tar.gz" *
fi
# удаляем следы
cd ..
rm -r ${format}
fi
let $[cont=$cont+1]
done

Вот такой скрипт. В конце хотел бы отметить для чего я складываю месячные бэкапы отдельно.
Пока не написал но вообще планирую прикрутить циклическую очистку, чтобы допустим было всего 30 копий а каждая следующая затирала самую старую, поэтому месячные и откладываю (а вдруг).