Application: "Bacula 5.2/7.4", "sqlcmd".
Задача: наладить выгрузку резервной копии "базы данных" СУБД "Microsoft SQL Server" посредством "Bacula".
Резервное копирование содержимого "баз данных" прямым копированием из файлов как правило невозможно и требуется предварительная выгрузка консистентного "дампа" в заранее известную директорию. Сделаем это, воспользовавшись встроенной возможностью "Bacula" исполнения произвольных скриптов на стороне клиента до и после процедуры непосредственного резервного копирования.
Предварительная настройка операционной системы.
В операционной системе должен быть исправна подсистема "теневого копирования" VSS (Microsoft Volume Snapshot Service, Shadow Copy), позволяющая обращаться к открытым и заблокированным файлам - без этого выгрузка "бинарного" дампа БД MSSQL невозможна.
Предварительная настройка СУБД.
Подготавливать к выгрузке "дампа баз данных" сервер СУБД "Microsoft SQL Server" практически не требуется. Нужен только доступ от имени обладающего достаточными привилегиями пользователя.
На практике аутентификация при подключении к MSSQL обычно осуществляется на уровне операционной системы, а сама СУБД берёт на себя определение политики доступа. Таким образом, несмотря на то, что пользователь "SYSTEM", от имени которого работает агент "Bacula", по определению имеет максимальные привилегии, в оснастке "Microsoft SQL Server" ему придётся явно выдать роль "sysadmin" - с меньшим уровнем доступа выгрузка резервных копий невозможна.
Насколько я уловил, СУБД MSSQL позволяет в один приём снимать "дамп" только одной БД, так что заранее выясняем, какие "базы данных" обслуживаются сервером:
C:\> sqlcmd -Q "sp_databases"
example_DB 28456
local_DB 2582784
....
local_DB 2582784
....
Конфигурирование "Bacula".
Дополняем описание задания резервного копирования сервиса СУБД "Microsoft SQL Server" следующими блоками конфигурации:
# vi /etc/bacula/client.d/example.net.conf
....
FileSet {
....
Include {
....
# Директория резервных копий "дампа базы данных"
File = "C:/bacula-mssql"
}
}
....
Job {
Name = "example.net"
Type = Backup
....
# Запуск выгрузки "бинарной" резервной копии целевой локальной "базы данных" MSSQL:
RunScript {
RunsWhen = Before
FailJobOnError = No
# Зачищаем и воссоздаём место для сохранения "дампа"
Command = "if exist c:\\bacula-mssql rmdir /s /q c:\\bacula-mssql"
Command = "mkdir c:\\bacula-mssql"
# Запускаем выгрузку резервной копии БД
# (первой операцией переменной "dbname" задаём имя БД, с которой снимаем "дамп")
Command = "SET dbname=example_DB & sqlcmd -Q \"SET LANGUAGE us_english; BACKUP DATABASE $(dbname) TO DISK='C:\\bacula-mssql\\$(dbname).bak'\""
}
#
RunScript {
RunsWhen = After
RunsOnFailure = yes
# По завершению всех процедур задания высвобождаем ресурсы
Command = "if exist c:\\bacula-mssql rmdir /s /q c:\\bacula-mssql"
}
}
FileSet {
....
Include {
....
# Директория резервных копий "дампа базы данных"
File = "C:/bacula-mssql"
}
}
....
Job {
Name = "example.net"
Type = Backup
....
# Запуск выгрузки "бинарной" резервной копии целевой локальной "базы данных" MSSQL:
RunScript {
RunsWhen = Before
FailJobOnError = No
# Зачищаем и воссоздаём место для сохранения "дампа"
Command = "if exist c:\\bacula-mssql rmdir /s /q c:\\bacula-mssql"
Command = "mkdir c:\\bacula-mssql"
# Запускаем выгрузку резервной копии БД
# (первой операцией переменной "dbname" задаём имя БД, с которой снимаем "дамп")
Command = "SET dbname=example_DB & sqlcmd -Q \"SET LANGUAGE us_english; BACKUP DATABASE $(dbname) TO DISK='C:\\bacula-mssql\\$(dbname).bak'\""
}
#
RunScript {
RunsWhen = After
RunsOnFailure = yes
# По завершению всех процедур задания высвобождаем ресурсы
Command = "if exist c:\\bacula-mssql rmdir /s /q c:\\bacula-mssql"
}
}
Проверяем корректность конфигурации и применяем таковую:
# bacula-dir -c /etc/bacula/bacula-dir.conf -t
# /etc/init.d/bacula-dir reload
# /etc/init.d/bacula-dir reload