Админу на заметку - 21. Используем PowerShell для синхронизации каталогов

|

powershell-synchronizing-000.png

В арсенале каждого системного администратора со временем накапливаются удобные инструменты, которые значительно облегчают выполнение ряда повседневных задач. Чаще всего это небольшие, но удобные утилиты или скрипты. Мы постоянно знакомим наших читателей с различными инструментами из нашей коллекции и на этот раз речь пойдет о простом, но достаточно функциональном PowerShell-скрипте для односторонней синхронизации каталогов.

Синхронизация каталогов - довольно часто встречающаяся задача, когда необходимо поддерживать соответствие содержимого в нескольких местах. От копирования данная операция выгодно отличается тем, что позволяет передавать только новые или измененные объекты, что позволяет существенно сократить трафик и время выполнения задачи. В Linux системах для этой цели есть мощная и удобная утилита rsync, а в Windows - robocopy, которые давно зарекомендовали себя и широко используются системными администраторами.

Но не так давно мы нашли один интересный PowerShell-скрипт который может послужить удобной заменой robocopy для простых задач автоматизации. Скрипт написан энтузиастом и выложен на сайте автора. Также архив со скриптом можно скачать по прямой ссылке. Внутри находится собственно скрипт Sync-Folder.ps1, который следует разместить в любом удобном месте.

Что интересного может предложить нам этот скрипт? На наш взгляд, основное его достоинство - это поддержка конфигурационных файлов в формате XML, в которых мы можем описать сразу несколько заданий с параметрами, которые будут выполнены последовательно. Кстати, robocopy тоже позволяет создавать файлы заданий, но один файл может содержать только одно задание и предназначен прежде всего для того, чтобы каждый раз не вводить все опции.

Давайте распакуем наш скрипт в произвольную папку, скажем C:\ADM и разместим там же файл конфигурации MySyncJob.xml. Будучи запущен без параметров скрипт ищет рядом с собой файл Sync-FolderConfiguration.xml и выполняет записанное в нем задание, это может быть удобно, но на наш взгляд удобнее давать конфигурационным файлам осмысленные наименования, что облегчит в последующем поиск нужных заданий, а также убережет от возможного нежелательного выполнения задания в случае случайного запуска скрипта. Все свои действия скрипт записывает в файл лога, который располагается в своей рабочей директории.

powershell-synchronizing-001.pngОткроем блокнотом XML-файл и внесем в него следующее содержимое (пример взят с сайта автора скрипта):

<Configuration>
<SyncPair>
<Source>C:\synctest\source1</Source>
<Target>C:\synctest\dest1</Target>
<Filter>*.txt</Filter>
<ExceptionList>
<Exception>*p234*.txt</Exception>
</ExceptionList>
</SyncPair>
<SyncPair>
<Source>C:\synctest\source2</Source>
<Target>C:\synctest\dest2</Target>
<Filter>*.txt</Filter>
</SyncPair>
</Configuration>

Начинается файл конфигурации с тега <Configuration>, который следует обязательно закрыть в конце. Задания синхронизации находятся внутри тегов <SyncPair>, обязательными являются два тега <Source> - путь к источнику данных и <Target> - место назначения. Можно указывать как локальные, так и сетевые расположения.

Тег <Filter> позволяет задать некоторую маску для копирования, например, только txt-файлы. Обратите внимание, что это именно маска, а не перечень расширений и т.п. Допускается использование подстановочных выражений, но фильтр может быть только один. Например, такая конструкция работать не будет, хотя ошибкой не является:

<Filter>*.jpg, *.png</Filter>

Использование в пределах одного задания двух тегов <Filter> приведет к синтаксической ошибке, поэтому если вам нужно копировать только файлы двух типов, скажем PNG и JPG, то следует создать два задания с одинаковыми параметрами, но разными фильтрами.

Заданное без подстановочных знаков выражение будет восприниматься буквально. Если вы хотите синхронизировать все файлы, содержащие в имени строку old, то следует указать:

<Filter>*old*</Filter>

А выражение

<Filter>old*</Filter>

отберет все файлы, которые начинаются с old, т.е. файл oldfile.txt будет скопирован, а fileold.txt - нет, в то время как с предыдущим фильтром были бы скопированы оба.

Кроме фильтра можно задавать исключения, которых может быть много и для их описания используется тег <ExceptionList>, внутри которого располагается список исключений, каждое из которых оформляется тегами <Exception>. В приведенном примере будут пропущены все файлы txt имеющие в имени строку p234.

После того, как файл конфигурации создан самое время проверить его в деле, запустим консоль PowerShell и запустим наш скрипт, указав ему пусть к конфигурационному файлу:

C:\ADM\Sync-Folder.ps1 -configurationfile:"C:\ADM\MySyncJob.xml"

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

powershell-synchronizing-002.pngЕсли вы отлаживаете сложный сценарий, то столь подробный лог окажется очень к месту, также можно включить интерактивный вывод результатов в консоль, используя ключ -Verbose:

C:\ADM\Sync-Folder.ps1 -configurationfile:"C:\ADM\MySyncJob.xml" -Verbose

powershell-synchronizing-003.pngЕсли необходимо вызывать скрипт из командной строки или пакетного файла, то следует использовать следующую конструкцию:

Powershell -Command "& {C:\ADM\Sync-Folder.ps1 -configurationfile:"C:\ADM\MySyncJob.xml"}"

В целях безопасности PowerShell-скрипты могут исполняться только интерактивно, т.е. сначала нужно запустить оболочку PowerShell, а затем в ней вызвать скрипт. В нашем случае сначала запускается оболочка, которой передается нужная команда на исполнение скрипта, аналогичная тому, как это было бы сделано интерактивно.

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

$PSScriptRoot

В итоге скрипт попытается записать файл лога не рядом с собой, а в корень диска C:, что обычно запрещено политиками безопасности и приведет к ошибке.

powershell-synchronizing-004.pngЧтобы добавить наш скрипт в планировщик заданий следует поступить аналогичным образом, создадим новую задачу, установим условия ее выполнения и на закладке Действия в качестве действия выберем Запуск программы, в поле Программа или сценарий укажем

Powershell

а в поле Добавить аргументы внесем команду на исполнение скрипта, также как мы это делали в командной строке:

-Command "& {C:\ADM\Sync-Folder.ps1 -configurationfile:"C:\ADM\MySyncJob.xml"}"

powershell-synchronizing-005.png

Как видим, данный скрипт не делает ничего такого, что не умела бы robocopy, но благодаря возможности использовать конфигурационные файлы позволяет упростить многие задачи по синхронизации данных. В один конфигурационный файл можно добавить нужное число заданий, а простой и структурированный синтаксис позволяет легко читать данные файлы. Добавьте к этому подробные и понятные логи.

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

Надеемся, что данный материал окажется вам полезен и указанный скрипт займет достойное место в применяемых вами инструментах.

 

Подписка на блог

Наш канал на YouTube Мы в Твиттере

Архивы по месяцам

Реклама

Статистика

 

Яндекс.Метрика

География

Flag Counter

Реклама

Об этой записи

Сообщение опубликовано 16.03.2017 22:06. Автор — Уваров А.С..

Предыдущая запись — Windows 7 и бесконечный поиск обновлений

Смотрите новые записи на главной странице или загляните в архив, где есть ссылки на все сообщения.

Реклама

Облако тегов