Как заставить административные сценарии работать быстрее
Несомненно, все, кто создает и использует в своей работе административные сценарии Windows Scripting Host (WSH), неплохо осведомлены о достоинствах этой технологии. Доступные из сценариев интерфейсы ADSI и WMI позволяют управлять учетными записями в каталогах SAM и Active Directory и обращаться к ресурсам операционной системы и приложений на локальном или удаленном компьютере. Благодаря тому что поддержка WSH изначально встроена во все операционные системы Microsoft, начиная с Windows 2000, от администратора требуется лишь минимальная подготовительная работа, чтобы начать применение административных сценариев в своей сети. Сценарии одинаково хорошо работают в доменах и в рабочих группах, а в модели рабочих групп административные сценарии могут в определенной степени компенсировать отсутствие штатных средств централизованного управления.
К сожалению, известна и другая сторона сценариев WSH — их медлительность при выполнении большинства задач удаленного администрирования. И дело не только в том, что серверы сценариев — cscript.exe и wscript.exe — представляют собой интерпретаторы. Самые длительные задержки происходят при подключении к объектам интерфейсов ADSI и WMI, когда выполняются процессы аутентификации и авторизации в домене или на удаленном компьютере. В пределах локальной сети успешное подключение занимает несколько секунд при аутентификации с локальными учетными записями и мало зависит от производительности административной рабочей станции и целевого компьютера. Однако при уже установленном ADSI-или WMI-соединении последующие управляющие действия выполняются без заметных задержек.
Хуже всего складывается ситуация, когда в процессе подключения возникают различные ошибки, особенно если целевой компьютер выключен или брандмауэр не разрешает входящий трафик по протоколам SMB или RPC. В этом случае сценарию требуется около минуты, чтобы получить сообщение об ошибке и только тогда продолжить выполнение. Легко оценить, что если такой сценарий выполняется в отношении сотни компьютеров и половина из них выключена, то время выполнения сценария составит более часа, причем основную часть времени сценарий будет безуспешно пытаться установить соединение с выключенными компьютерами.
Рассмотрим различные методы повышения производительности административных сценариев, выполняющихся под управлением операционных систем Windows 2000 и выше. Предварительно отметим, что по умолчанию в Windows 2000 установлен сервер сценариев WSH версии 5.1, а в Windows XP и выше — WSH 5.6. Для Windows 2000 версию 5.6 можно бесплатно загрузить с сайта Microsoft и установить в качестве обновления (см. врезку «Источники информации»). Кроме того, вне зависимости от версии WSH, в интерфейсе WMI Windows XP появились классы, объекты, методы и свойства, которые недоступны в Windows 2000. За исключением примера из листинга 1, все приведенные ниже сценарии должны запускаться под управлением версии WSH 5.6.
Работа над ошибками
Производительность административных сценариев можно существенно повысить, если избегать бесполезных соединений с неработающими компьютерами. Проще всего проверить доступность удаленного компьютера с помощью команды ping. Этот способ был подробно рассмотрен в статье Боба Уэллса «Удаленное администрирование с помощью WMI» в № 2 Windows IT Pro/RE за 2003 год и представлен здесь в несколько модифицированном варианте (см. листинг 1). В таком виде сценарий совместим с обоими серверами сценариев (cscript.exe и wscript.exe) и не зависит от локализации операционной системы. Фактически проверка состоит в выполнении командной строки
ping.exe -n 2 <имя или IP-адрес компьютера> | find.exe «TTL=»
Данная командная строка возвращает код завершения errorlevel = 0 в случае успешного выполнения команды ping (в отклике ping, независимо от языковой версии Windows, будет присутствовать подстрока «TTL=»), и errorlevel = 1, если удаленный компьютер не отвечает. Код возвращения передается методу WshShell.Run и может быть проанализирован. Еще одним достоинством метода Wshell.Run является возможность запускать командную строку в невидимом окне, что удобно при использовании сервера сценариев wscript.exe.
Если административные сценарии разрабатываются для использования только под управлением Windows XP или Windows Server 2003, то целесообразно воспользоваться встроенным WMI-классом Win32_PingStatus, как показано в листинге 2. В этом случае проверка отклика целевого компьютера будет выполняться быстрее, чем в предыдущем примере.
Следует отметить, что проверка доступности компьютеров с помощью ping в сценариях имеет и самостоятельное значение, поскольку позволяет быстро, хотя и не точно, отслеживать присутствие компьютеров в сети.
Строго говоря, предложенный подход имеет один недостаток — тестирование удаленного компьютера и последующее подключение производятся по разным протоколам. Можно представить ситуацию, когда на целевом компьютере будет запущен локальный брандмауэр, разрешающий ICMP-трафик, но блокирующий входящие соединения на порт RPC (TCP 135). Тогда проверка посредством команды ping сообщит о доступности компьютера, а последующее подключение к интерфейсу WMI будет ожидать тайм-аута около минуты. К сожалению, не существует стандартного способа задать тайм-аут ADSI- и WMI-соединений. С другой стороны, известно, что в локальной сети успешная аутентификация происходит в течение первых нескольких секунд, и если она не произошла сразу, остается только ожидать сообщения об ошибке соединения. Можно ли прервать соединение, если уже ясно, что оно не будет успешным? Возможное решение проиллюстрировано в листингах 3 и 4. Функция FnSetPass, рассматриваемая в качестве примера, изменяет пароль пользователя на удаленном компьютере. Функция возвращает True, если изменение пароля прошло успешно, либо False — в случае неудачи. Функция FnSetPass может быть использована в составе сценария для смены пароля локального администратора на компьютерах в домене или в рабочих группах. Актуальность такой задачи была рассмотрена достаточно подробно в статье Сергея Гордейчика (см. врезку «Источники информации»).
В сценарии использован метод WshShell.Exec, позволяющий запустить внешнее приложение (в том числе и другой сценарий) и сохранить над ним определенный контроль. Метод создает объект класса WshScriptExec. Обратившись к свойству WshScriptExec.Status, можно узнать, завершилось ли внешнее приложение или продолжает выполняться, а с помощью свойства WshScriptExec.ExitCode — получить код завершения. Кроме того, используя метод WshScriptExec.Terminate, можно в любой момент закрыть запущенное приложение.
Функция FnSetPass состоит из двух составляющих — собственно функции (листинг 3) и отдельного файла сценария setpass.vbs (листинг 4). Этот файл представляет собой функционально законченный сценарий, предназначенный для смены пароля пользователя на удаленном компьютере. Именно в этом файле выполняются все действия по созданию ADSI-соединения и изменению пароля. В качестве параметров командной строки в сценарий передаются: имя или IP-адрес компьютера, имя пользователя и новый пароль, а также реквизиты учетной записи администратора на целевом компьютере либо в домене. В последнем случае имя задается в стандартном формате <Домен><Администратор>. Если изменение пароля прошло успешно, то сценарий возвращает нулевой код завершения. В случае каких-либо ошибок выполнение сценария прерывается и с помощью метода Wscript.Quit(n) формируется код завершения, отличный от нуля.
Хотя сценарий setpass.vbs можно запускать и сам по себе, он не содержит никаких средств оптимизации. Всю необходимую функциональность обеспечивает управляющая функция FnSetPass.
Данная функция запускает сценарий в качестве внешнего приложения и каждую секунду проверяет, завершился ли он или продолжает выполняться. В первом случае анализируется код завершения. В зависимости от него функция принимает значения True или False. Иначе говоря, функция продолжает проверять состояние сценария и по истечении интервала времени, задаваемого константой intTimeOut (в нашем примере 15 секунд), прерывает работающий сценарий. При этом в качестве значения функции возвращается False. Важно отметить, что функция FnSetPass даже «не знает», что именно делает запускаемый ею сценарий. Она будет работать одинаковым образом с любыми административными сценариями ADSI и WMI, в которых ввод данных производится через параметры командной строки, а ошибка выполнения или ее отсутствие определяется кодом завершения. Используя описанный метод, можно до некоторой степени компенсировать длительные тайм-ауты неудачных ADSI- и WMI-соединений.
Многозадачные сценарии
Перечисленные меры позволяют в несколько раз повысить производительность административных сценариев, однако далеко не исчерпывают резервов оптимизации. Звучит невероятно, но административные сценарии можно заставить выполняться в десятки раз быстрее!
Основная ценность административных сценариев состоит в возможности централизованного управления множеством компьютеров. Обычно такие сценарии работают со списком целевых компьютеров, которые могут быть перечислены в файле, каталоге LDAP, электронной таблице или базе данных. Однако независимо от представления сценарий последовательно обращается к компьютерам из списка и переходит к следующему компьютеру только после завершения соединения с текущим компьютером. Иными словами, в каждый момент времени сценарий обращается только к одному компьютеру. Именно так выполняется сценарий из упоминавшейся ранее статьи, предназначенный для смены пароля локального администратора на рабочих станциях в домене.
Даже в случае успешного подключения период ожидания составляет несколько секунд, пока не завершатся процессы аутентификации и авторизации ADSI- или WMI-соединений. Просмотр счетчиков производительности показывает, что ресурсы процессора в это время используются незначительно. Отсюда можно сделать вывод, что метод последовательного обращения к целевым компьютерам оказывается крайне неэффективным в административных сценариях, хотя и весьма популярным ввиду своей простоты и доступности. Решение проблемы состоит в одновременном управлении многими компьютерами. Для этого на административной рабочей станции должен параллельно выполняться не один, а множество сценариев, а сами сценарии должны приобрести сходство с многозадачными приложениями.
Строго говоря, многозадачность не поддерживается в пределах одного сервера сценариев. Например, невозможно создавать потоки команд, не существует стандартного способа обмениваться данными между двумя работающими сценариями. Также несколько сценариев не могут одновременно производить запись в один и тот же файл. Тем не менее, применяя методы WshShell.Run и WshShell.Exec, можно запускать vbs-файлы в новых экземплярах серверов сценариев, обеспечивая одновременное выполнение многих сценариев. Для передачи данных в запускаемые дочерние сценарии удобно использовать аргументы командной строки. Если сценарий не должен выполняться в течение определенного интервала времени (например, ожидая результатов работы другого процесса), то он может быть приостановлен с помощью метода Wscript.Sleep t, где t — время в миллисекундах. Все это время сценарий не будет расходовать вычислительные ресурсы.
Метод управления, проиллюстрированный в листингах 3 и 4, может быть распространен на множество экземпляров административного сценария. Тогда, по аналогии с рассмотренным выше примером, структура многозадачного сценария разделяется на независимые компоненты — собственно административный сценарий и менеджер задач. Последний представляет собой универсальный сценарий, управляющий запуском и одновременной работой многих процессов WSH, в которых выполняются экземпляры административного сценария. Код менеджера задач остается неизменным при использовании с различными административными сценариями. Практический, готовый к применению вариант такого универсального менеджера задач представлен в листинге 5 (файл tasks.vbs).
Для дальнейшего рассмотрения вернемся к сценарию setpass.vbs. Он может быть запущен самостоятельно из командной строки со следующими параметрами:
setpass.vbs <Компьютер> <Пользователь> <Новый пароль> <Администратор> <Пароль администратора>
Нулевой код завершения будет означать успешную смену пароля.
Используя сценарий tasks.vbs, теперь не составляет проблем выполнить аналогичную операцию на множестве компьютеров. Для этого перечислим имена или IP-адреса компьютеров в текстовом файле, например computers.txt (по одному имени или IP-адресу в каждой строке) и затем укажем в командной строке
tasks.vbs setpass.vbs computers.txt <Пользователь> <Новый пароль> <Администратор> <Пароль администратора>
Здесь и далее предполагается, что в качестве сервера сценариев по умолчанию установлен wscript.exe, в противном случае следует указать wscript.exe в самом начале командной строки. Как результат процессы смены пароля запустятся на множестве компьютеров одновременно. Константа ScriptLimit в файле tasks.vbs ограничивает максимальное число процессов WSH в многозадачном сценарии. Ее значение (по умолчанию 50) имеет замечательный физический смысл — примерно во столько раз возрастает производительность многозадачного сценария по сравнению с обычным. Например, сценарий смены пароля локального администратора, выполняющийся в отношении примерно 500 компьютеров, часть из которых может быть выключена, завершится в течение 2-3 минут, а не нескольких часов, как было раньше! Значение константы ScriptLimit можно подбирать опытным путем: его увеличение повышает быстродействие сценария, но при условии, что в системе имеется достаточно свободной физической памяти для запуска необходимого числа экземпляров серверов сценариев.
В процессе выполнения сценария создается текстовый файл со списком компьютеров, в отношении которых не удалось успешно выполнить административный сценарий. Имя файла образуется путем прибавления суффикса _failed к имени файла, содержащего исходный список компьютеров, например computers_failed.txt. Характер ошибок не фиксируется. В дальнейшем такой файл можно переименовать и снова использовать совместно с менеджером задач tasks.vbs.
Теперь все, что нужно для эффективного управления множеством компьютеров, — это написать сценарий, выполняющий требуемую административную задачу на одном удаленном компьютере. При этом должны соблюдаться следующие условия, которые, впрочем, легко выполнимы.
- Все данные должны передаваться в административный сценарий в качестве аргументов командной строки, причем первым аргументом должно быть имя (или IP-адрес) целевого компьютера.
- В случае успешного выполнения административный сценарий должен возвращать нулевой, а при любой ошибке - отличный от нуля код завершения.
- Если в командной строке указано неверное число аргументов, то сценарий должен возвратить предопределенный код завершения. В сценарии tasks.vbs таким кодом выбрано число 9. Благодаря данному условию не допускается запуск многочисленных процессов WSH, если командная строка содержит ошибку в имени административного сценария.
В общем случае, если существует административный сценарий admscript.vbs, отвечающий перечисленным требованиям и запускаемый в командной строке
admscript.vbs <Компьютер> <Список аргументов>
то, помещая в текстовом файле список компьютеров и используя менеджер задач tasks.vbs, можно запустить административный сценарий в многозадачном режиме:
tasks.vbs admscript.vbs <Путь к файлу> <Список аргументов>
Кроме имен или IP-адресов компьютеров, в текстовом файле можно указывать и другие параметры, передаваемые в административный сценарий. Это особенно удобно, если некоторые параметры являются специфичными для компьютеров из списка. Параметры следует перечислять через пробел после имени компьютера, а их порядок должен соответствовать порядку, определенному в административном сценарии. При этом часть аргументов, общих для всего списка компьютеров, можно по-прежнему задавать в командной строке. Отсюда возникает еще одно условие, которого желательно придерживаться при разработке административных сценариев: параметры командной строки, которые могут оказаться специфичными для компьютера, следует помещать сразу после имени компьютера, и только затем идут общие параметры.
В заключение приведем простой пример сценария WMI, рассчитанного на совместную работу с менеджером задач tasks.vbs. В сценарии (листинг 6) осуществляются подключение к удаленному компьютеру и последующая модификация реестра. Аутентификация происходит с локальной административной учетной записью на целевом компьютере. Вносимые изменения эквивалентны установке значения Send NTLMv2 response only/Refuse LM & NTLM в правиле политики безопасности Local PoliciesSecurity OptionsLAN Manager Authentication Level. Для запуска сценария следует указать в командной строке:
tasks.vbs lmauth.vbs <Путь к файлу> <Администратор> <Пароль администратора>
Подобные сценарии могут использоваться для централизованного управления серверами и рабочими станциями в сетях, не основанных на каталоге Active Directory. В условиях доменной инфраструктуры те же задачи стандартно решаются посредством групповых политик.
Оправданный подход
Из других средств, в которых реализовано удаленное управление компьютерами в многозадачном режиме, отметим утилиту Security Configuration Wizard, входящую в состав Service Pack 1 для Windows Server 2003. Если предполагается развернуть политику безопасности из командной строки (т. е. выдать команду scwcmd configure), то с помощью необязательного параметра /t: можно указать количество потоков, в которых выполняются параллельные операции по настройке целевых серверов.
Рассмотренные методы оптимизации позволяют выйти на качественно новый уровень управления с помощью сценариев. Медлительность сценариев более не составляет проблемы. Теперь, запуская административный сценарий в большой сети, можно не планировать другую работу, ожидая завершения сценария. Многозадачный сценарий выполнится за несколько минут, даже если локальная сеть будет насчитывать сотни компьютеров.
Олег Ржевский - Руководитель проекта в Инвестиционном банке ТРАСТ, к.ф-м.н. Имеет сертификат MCSE. osr@trust.ru
Источники информации
- www.microsoft.com/downloads, в строке поиска указать "Windows Script 5.6".
- Уэллс Б. Удаленное администрирование с помощью WMI// Windows IT Pro/RE, 2003, № 2, с. 16-19.
- Гордейчик С. Локальная угроза// Windows IT Pro/RE, 2003, № 3, с. 56-58.
- Комар Б. Security Configuration Wizard из Windows 2003 SP1// Windows IT Pro/RE, 2005, № 4, с. 41-44.