python

Python + vshadow + robocopy — синхронизация каталога с удаленной машиной

  • пятница, 31 октября 2014 г. в 02:10:34
http://habrahabr.ru/post/241931/

Не так давно у меня встала задача копировать базу данных из удаленного филиала для получения в нашем офисе ее полной копии на момент создания. По идее ежедневное копирование. Первое, что пришло на ум, это rsync сервер, на который выполняется копирование, а уже с него копия используется далее. Быстрый поиск навел на боле менее адекватную инструкцию тут же.

Проблема в том, что на клиентской машине стоит Win система. И принимающая сторона тоже использует аналогичную OS. Rsync сервер на Linux — это лишняя прослойка между двумя машинами. Ставить Rsync на Win сервере возможно, но по другим отвлеченным соображениям, излишне. В итоге наткнулся на свой скрипт синхронизации каталогов и совместив его с созданием теневой копии создал новое решение.

Получившийся скрипт полностью здесь. В статье просто приведу основные вехи и полученный функционал.

Скрипт создает теневую копию диска. Выполняет копирование заданных каталогов на удаленный ресурс по smb. Вычислят отличия между источником и полученной копией. Формирует отчет о копировании и полученных отличиях, после чего отправляет по почте отчет заданным адресатам.

Как и в выше указанной статье, для начала качаем Volume Shadow Copy Service SDK 7.2 с сайта Microsoft. Устанавливаем на машину и выдергиваем нужные нам утилиты.
Нам понадобятся vshadow.exe и vshadow.pdb файлы из этого SDK. Внимание — они разные для 64-битных, и 32-битных систем.

После инсталляции их можно будет найти тут:

64-bit — %PROGRAMFILES%\Microsoft\VSSSDK72\TestApps\vshadow\bin\obj-chk\amd64
32-bit — %PROGRAMFILES%\Microsoft\VSSSDK72\TestApps\vshadow\bin\release-xp


Складываем в отдельный каталог. Я обычно создаю под разные задачи каталог c:\Windows\!Script и в нем уже подкаталоги. Тут личное дело каждого. Полученные два файла и скрипт можно копировать на целевую машину и подгонять скрипт под свои задачи. А вот Python необходимый для выполнения скрипта придется устанавливать на каждой клиентской машине.

Непосредственно тело скрипта начинается со строки 137. Для настройки целей копирования и прочего сопутствующего хозяйства требуется определить переменные.

####################
##  Переменные        ##
####################
work_dir = 'C:\Windows\!Script\Backup'             # рабочий каталог скрипта. Изменить на тот в который выложенна утилита vshadow.exe и сам скрипт
source_disk = 'c:'
destin_disk = 'o:'
param_script = 'vs_generated.cmd'
# список каталогов для копирования
cwd_list = [['o:\\Windows\\!Script\\Backup', '\\\\master\\apps\\temp\\viv\\backup'],['o:\\ocs-ng', '\\\\master\\apps\\temp\\viv\\ocs-ng']]
# настройка почты
from_addr = 'admin@typa.ru'                                       # адрес отправителя отчета
tech_addr = ['user1@typa.ru', 'user1@typa.ru']           # список адресатов


В данном случае это рабочий каталог, в котором находится скрипт, целевой диск с копией, имя диска, к которому будет примонтированна созданная теневая копия, название файла, в который утилита vshadow.exe сохраняет значения своих переменных. Далее переменная cwd_list содержит список каталогов, которые требуется копировать и места куда выполнять копирование. Переменная содержит список из двух элементных списков. Обратите внимание, что для экранирования косой черты в путях в Python ее требуется проставлять два раза, а для указания ссылки на сетевой путь — даже четыре.

И завершает определение переменных настройки отправки электронной почты. Переменная, содержащая адрес отправителя письма и переменная, содержащая список получателей.

Собственно, определить переменные в этой секции — это все, что требуется для успешной работы. Далее вешаем выполнение скрипта в планировщик заданий, не забывая указывать выполнение с правами администратора. Без админ прав создание теневой копии не происходит. Если копировать будем на сетевой ресурс в домене, желательно завести под это специально заведенную учетную запись в домене. Соответственно, права на целевой каталог в домене задаем для этой учетной записи под наши предпочтения. Следует учесть, что утилита robocopy имеет много опций для своего запуска. В данном случае идет синхронизация каталога источника и удаленного каталога полностью, вплоть до ntfs прав, аудита и владельца каталога. В общем, для сетевого каталога придется еще повозится с заданием первоначальных прав ntfs на расшаренном сетевом ресурсе. Если вся эта информация вам не требуется, можно просто убрать лишние ключи в вызове копирования.

Ну и в завершение быстро пройдусь на основных вехах в работе скрипта.

Со строки 169 выполняем создание теневой копии.

# проверяем наличие файла создания теневых копий
# без него работать не будем поэтому выход с ошибкой
if not(path.exists(getcwd() + '\\vshadow.exe')) and not(path.isfile(getcwd() + '\\vshadow.exe')) :
        exit(1)
proc = Popen('vshadow.exe -nw -p -script=' + param_script + ' ' + source_disk, shell=True, stdout=PIPE)
proc.wait()
out = proc.stdout.readlines()

Обратите внимание на параметр вызова -script=' + param_script, в результате работы vshadow.exe в этот файл выкладываются значения переменных. Нас из них интересует только SHADOW_ID_1, которая содержит идентификатор созданной теневой копии. Собственно, далее мы занимаемся тем, что читаем полученный файл и выдергиваем значение идентификатора для дальнейшей работы. И после того, как нашли идентификатор, подключаем теневую копию.

proc = Popen('vshadow.exe -el=' + SHADOW_ID + ',' + destin_disk, shell=True, stdout=PIPE)

Далее все рутинно. Перебираем список копирования. Натравливаем на него robocopy. Читаем логи формируем отчет. В завершении, отправляем отчет всем заинтересованным. Удаляем теневую копию и файл, содержащий переменные от vshadow.exe

P.S. Кстати, если при запуске этого скрипта файл определения остался, vshadow не сможет его переписать и скрипт будет пытаться подключить старую теневую копию по ее id. По идее в дальнейшем не помешает проверять наличие этого файла еще и в начале работы и удалять при необходимости.

P.P.S. Обратите внимание, что выполняется копирование каталогов. Если есть желание копировать диск целиком, требуется немного изменить процедуру sync. При копировании ведется лог и имя лог файла получается из названия каталога источника. Если будет указан просто диск, имя, лог файла сформируется что-то типа 'o:.txt' и скрипт выпадет с ошибкой. В данном случае лучше добавить проверку того, что все символы в полученном имени файла допустимы и удалять прочие.