Строим сценарий: шаг за шагом

Часто неполадки в компьютере возникают из-за прекращения работы какой-нибудь службы. Проверить статус служб, чтобы убедиться в их активности, — хороший диагностический прием. На локальной машине можно просто открыть оснастку Computer Management консоли управления Microsoft Management Console (MMC) и заглянуть в раздел Services and Applications, Services. Но как быстро и без хлопот проверить службы на удаленных компьютерах? Если Windows 2000 Server Terminal Services работает в режиме Remote Administration, то можно воспользоваться программой Remote Desktop Connection компании Microsoft, но для этого требуется выполнить подготовительные шаги. Кроме того, данный вариант возможен лишь на компьютерах, принимающих входящие запросы RDP. Лучше — особенно если необходимо провести инвентаризацию большого числа компьютеров — составить сценарий для проверки состояния службы на любом компьютере, совместимом с WMI (Windows Management Instrumentation).

В статье «Сценарии WMI для начинающих» (опубликованной в Windows 2000 Magazine/RE № 5 за 2001 год) я рассказывала о том, как упростить задачи управления компьютером с помощью WMI. Интерфейс WMI обеспечивает доступ ко многим физическим и логическим компонентам компьютера. В данной статье я покажу, как построить сценарий с именем GetServiceStatus.vbs, который устанавливает связь с WMI на сервере и использует его для подготовки списка служб на этой машине. С помощью GetServiceStatus.vbs можно проверить состояние локального сервера, удаленного сервера, группы удаленных серверов или всех серверов домена. Объясняя, как работает GetServiceStatus.vbs, я расскажу о способах организации данных, применении аргументов в сценариях и константах, которые можно использовать для разделения выходных данных символами табуляции и возврата каретки.

Сбор информации о состоянии служб

Основные операции GetService Status.vbs — подключение к конкретному серверу, подготовка списка служб, доступных на этом сервере, и отображение статуса каждой службы. Все остальные действия сценария обеспечивают выбор группы проверяемых серверов.

Для выполнения основных задач я присвоила имя сервера переменной (sComputerName), установила связь с пространством имен WMI на этом сервере и зарегистрировалась с административными полномочиями, чтобы получить нужную информацию. Затем сценарий извлекает полный список всех служб на сервере и отображает имя и текущее состояние каждой службы (например, запущена, остановлена, приостановлена) через символ табуляции. В листинге 1 показано, как сценарий проверяет службы. В этом фрагменте исходного текста жестко задано имя сервера (Alien), но настоящий сценарий является более гибким.

Исходный текст в листинге 1 позволяет пользователю с административными полномочиями в домене установить связь со службой WMI на другой машине, просто указав в переменной sComputerName имя компьютера, на котором предстоит запустить программный код. Для выполнения сценария на удаленном компьютере требуется немного больше времени, чем на локальном, но в локальной сети различие невелико — оно не превышает времени, необходимого для подключения к службе на удаленном компьютере. Машина, на которой выполняется программный код, выдает список всех активных служб. На экране 1 показан фрагмент примера списка.

Однако редактировать сценарий всякий раз при проверке состояния служб на новом компьютере неудобно. Если настроить сценарий на использование в качестве аргументов имен компьютеров, сохраненных в текстовом файле или полученных из Active Directory (AD), то с помощью сценария можно получить отчеты о любых машинах, от конкретного сервера до всех компьютеров, работающих с WMI и способных установить связь со сценарием.

Имена компьютеров как аргументы

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

Все аргументы VBScript — пронумерованные по порядку начиная с 0 — хранятся в наборе с именем Wscript.Arguments. Пользователь выбирает аргумент из набора, указывая имя набора, за которым следует порядковый номер аргумента в круглых скобках. Таким образом, запись Wscript.Arguments(0) указывает на первый аргумент в наборе, а Wscript.Arguments(3) — на четвертый аргумент. Даже если набор содержит лишь один аргумент, при обращениях к нему из сценария необходимо указать номер этого аргумента. Сценарий не нуждается в специальном коде для получения или сохранения аргументов — GetServiceStatus.vbs присваивает значение аргумента переменной исключительно для того, чтобы было проще работать с ним.

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

Что произойдет, если имя сервера указано неверно — например, из-за опечатки или потому, что сервер отключен от сети? Это важный вопрос, так как невозможно получить информацию о службах несуществующего компьютера. Пока я просто использовала оператор On Error Resume Next, чтобы сценарий игнорировал любые ошибки и продолжал работу.

Альтернативные способы ввода аргументов

Имена серверов — не единственные аргументы, которые можно ввести в сценарий. Можно указать сценарию источник входных данных, и он будет считывать информацию из текстового файла, содержащего список имен серверов, или проверит все серверы домена. Альтернативный способ — попросить сценарий о помощи. Если пользователь не вводит никаких аргументов, то сценарий может предположить, что имеющиеся аргументы представляют собой имена компьютеров, на которых нужно выполнить сценарий. Как проверить все эти варианты? Пока я просто организую сценарий, чтобы он мог работать по-разному в зависимости от вводимых данных. Позже я покажу, как сценарий производит те или иные действия с этими данными.

Если пользователь не вводит никаких аргументов, то сценарий должен работать на локальном компьютере. Чтобы проверить службы локального компьютера без жесткого указания или ввода имени локального сервера, можно использовать синтаксис WMI. Можно указать текущий компьютер по имени, но можно ввести точку (.), чтобы WMI запустил сценарий на локальной машине. Сценарий работает локально по умолчанию, если настроить его на проверку значения Wscript.Arguments(0) — первого элемента в наборе Arguments. Если элемент пуст, то переменной sComputerName присваивается значение (.).

Еще один вариант — извлечение списка имен серверов из текстового файла. Местонахождение текстового файла должно быть неизменным, чтобы жестко запрограммировать его в сценарии. Однако пользователь должен как-то указать сценарию, что требуется прочитать файл. Для этого можно проверить, не содержится ли в элементе Wscript.Arguments(0) значение file.

Можно настроить сценарий на проверку всех компьютеров в AD или какого-нибудь подмножества компьютеров, заданного в сценарии. Для простоты рассмотрим пример со всеми компьютерами. Чтобы проверить состояние служб на всех компьютерах с интерфейсом WMI, пользователь должен ввести аргумент all. Аналогично можно ввести имя организационной единицы — OU — в качестве аргумента, протестировать входные данные, чтобы убедиться, что это OU, а затем проверить только компьютеры указанной OU.

Поскольку сценарий принимает входные данные различных типов, ему необходимы некоторые дополнительные инструкции. Ранее в моих статьях о сценариях с аргументами не рассматривался случай отсутствия аргументов. Если пользователь, запустивший сценарий, не указал необходимых аргументов, сценарий предупреждал об отсутствии входных данных и прекращал работу. Для данного сценария такой подход неприемлем, так как без аргументов он будет запущен на локальном компьютере. Поэтому я дала пользователю возможность получить подсказку с помощью знакомой команды /?. Если сценарий обнаруживает эту комбинацию символов в элементе Wscript.Arguments(0), то выводит на экран рекомендации по работе со сценарием.

Я уже использовала операторы Select Case во многих статьях, поэтому читателей не должно удивить, что я применяю его в данном сценарии для проверки входных значений. В листинге 3 показан фрагмент сценария, который решает, как интерпретировать входные данные. Сценарий преобразует входные данные в нижний регистр (чтобы избежать противоречий; ALL, All и all — не одинаковые строковые значения), проверяет значение Wscript.Arguments(0) и выполняет программный код в соответствии с этим значением. Очевидно, что окончательная версия сценария будет не просто сообщать о режиме работы сценария, но в листинге 3 показана только общая структура. Теперь у нас есть механизм для ввода другой информации, помимо имен серверов.

Чтение из текстового файла

Если требуется проверить несколько имен серверов или всегда проверять одни и те же серверы, то проще сохранить имена в файле, чем вводить их с клавиатуры при каждом запуске сценария. Если всегда запускать сценарий с одного компьютера, то можно сохранить имена серверов в файле с именем servers.txt (по одному имени сервера в каждой строке), а затем вызвать файл из сценария. Для чтения файла используется COM-объект VBScript с именем File System Object (FSO) — VBScript не знает, как взаимодействовать с файлами, но умеет работать с COM-объектами. Объекты FSO могут представлять папки или файлы; в этом случае FSO используется для выбора и считывания текстового файла, в котором хранятся имена серверов. Имя файла не изменяется, поэтому его можно указать в сценарии как константу, а не как переменную (листинг 4).

Если нужно создать сценарий для чтения файлов из разных источников без редактирования сценария, то можно сделать имя файла первым аргументом, а путь к этому файлу — вторым аргументом. Для этого достаточно сделать значение INPUT_FILE_NAME равным Wscript.Arguments(1), так как в этом аргументе будет храниться путь.

Прежде чем работать со строкой имен, составляющих переменную sComputerName, необходимо составить массив имен. В самой простой и распространенной форме массивы представляют собой таблицы данных из одного столбца, строки которых идентифицируются индексным указателем от 0 до номера последней строки — верхней границы массива. Можно создать массив и заполнить его вручную или создать массив и ввести в него блок существующих данных. При формировании массива из существующих данных следует воспользоваться функцией Split, чтобы разделить содержимое переменной sComputerName на фрагменты с символами возврата каретки/перевода строки (vbCrLf) в качестве разграничителя. Исходный текст, который преобразует содержимое sComputerName в массив aComputers, выглядит следующим образом:

aComputers = Split(sComputerName, vbCrLf)

Сформировав массив, можно обработать данные в нем оператором For Each...Next, чтобы вывести имя каждого компьютера и отобразить его службы вместе с их статусом.

Чтение имен компьютеров из AD

Для полной инвентаризации служб на всех серверах в AD (или части AD) можно прочитать имена непосредственно из контроллера домена (DC) вместо того, чтобы вводить их вручную или считывать из текстового файла. Такой способ связи с серверами гарантирует инвентаризацию только имеющихся в наличии серверов — без потенциальных проблем из-за ошибок при вводе имен — но при этом сильно возрастает объем выходных данных.

Получить список серверов просто: нужно подключиться к службе LDAP (Lightweight Directory Access Protocol — упрощенный протокол доступа к каталогам) на DC, извлечь имена всех компьютеров из AD (или части AD) и поместить эти имена в набор. Затем следует обработать список имен с помощью оператора For Each...Next, получить стандартное имя (common name — CN) каждого компьютера и воспользоваться этой информацией, чтобы выяснить статус служб на каждом компьютере. Например, для запроса к содержимому контейнера Computers используется исходный текст листинга 5. Остальная часть оператора For Each...Next составляет список служб на каждом компьютере и сообщает их статус.

Перенаправление вывода

В листинге 6 показан собранный сценарий, GetServiceStatus.vbs. Этот сценарий может генерировать большой объем данных, поэтому при проверке трех и большего числа серверов я рекомендую не пытаться читать информацию из командного окна. Лучше перенаправить вывод в файл:

getservicestatus.vbs [arguments]

> status.txt

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


Криста Андерсон — независимый автор и консультант журнала Windows NT Magazine.

С ней можно связаться по адресу: candersn@adelphia.net.

Поделитесь материалом с коллегами и друзьями