Продолжаю допиливать SCOM2012R2. На сей раз решил разобраться с периодически возникающим алёртом вида:

Алёрт этот генерируется правилом “Workflow Runtime: Failed to run a process or script” из пакета управления System Center Core Monitoring. Однако выключать правило не стоит. Оно просто реагирует на события, возникающие в логе “Operations Manager” при сбое выполнения скрипта.  А вот сам скрипт вызывается монитором: “The required SCOM hotfixes for Exchange MP are not installed.” из пакета управления “Exchange Server 2010″.

Этот монитор проверяет, подходит ли версия агента SCOM, установленная на сервер Exchange для работы пакета управления Exchange MP. Дело в том, что ранние версии агентов глючили с этим пакетом управления.

Посмотрим, что там не ладно со скриптом.

Возьмём скрипт прямо из консоли оператора и скопируем в редактор с подсветкой синтаксиса.

Судя по алёрту, скрипт вылетает на первой строке вот этой конструкции:

Запустим скрипт на сервере с установленным агентом SCOM, чтобы убедиться в этом.

C:\temp>cscript c:\temp\hotfix1.vbs //nologo
c:\temp\hotfix1.vbs(120, 10) Microsoft VBScript runtime error: Subscript out ofrange: ‘count’

Да, так и есть, ошибка именно в скрипте.

Давайте разберём скрипт до места вылета. Скрипт довольно простой. Правильными считаются версии SCOM старше “6.0.6278.100″ и “6.1.7221.2″. Точнее, скрипт берёт версию агента SCOM на сервере Exchange, и если она начинается с 6.0 (SCOM2007 и SCOM2007SP1), то эталонной будет версия “6.0.6278.100″, а если она начинается с 6.1 ((SCOM2007R2), то эталонной считается “6.1.7221.2″.

Дальше скрипт узнаёт версии библиотек HealthService.dll и Microsoft.EnterpriseManagement.DataWarehouse.DataAccess.dll и сравнивает их с эталонной. Если хотя бы одна из библиотек старая, то скрипт вернёт в монитор значение BAD, и монитор сгенерирует алёрт:

Если агент новее эталона, то алёрт сгенерирован не будет.

Итак, давайте пробежимся по скрипту с самого начала, чтобы понять, почему он останавливается по ошибке.

Здесь задаются эталонные версии SCOM. И сразу видно потенциальную роблему. У меня развёрнут SCOM2012R2, версия агента: 7.1.10226.0. Не похоже, чтобы скрипт знал о существовании SCOM новее 2007R2.

 

Здесь из значения реестра реестра “HKLM\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Setup\CurrentVersion” берётся  версия SCOM. Также выясняются версии библиотек HealthService.dll и Microsoft.EnterpriseManagement.DataWarehouse.DataAccess.dll

 

Здесь из двух эталонных версий выбирается одна. Если версия агента начинается с 6.0 – агент SCOM2007 и SCOM2007SP1, то за эталон принимается “6.0.6278.100″, если версия агента начинается с 6.1 = агент SCOM2007R2, то эталон – “6.1.7221.2″.

У нас версия агента начинается с 7.1. Значит, переменная hotfixVersion останется пустой, нехорошо как-то получается.

 

Здесь версии библиотек сравниваются с эталоном. В нашем случае они сравниваются с пустым значением – ой не к добру это. Посмотрим, как происходит сравнение версий.

 

Проверяемая и эталонная версии разбиваются на массивы по разделительным точкам. Дальше вычисляются длины двух полученных массивов, берётся меньшая и идёт сравнение версия по числам слева направо.

К примеру, если бы у нас был агент версии “6.1.7555″, то скрипт получал бы 2 массива:

эталон: 6, 1, 7221, 2 – длина массива – 4

текущая версия: 6, 1, 7555 – длина массива – 3

Дальше было бы сравнение первых трёх элементов массива

6 = 6,

1 = 1,

7221 < 7555

Текущая версия больше эталонной, значит всё в порядке.

В нашем же случае текущая версия – 7.1.10226.0. А эталон вообще пустой. Длина массива добывается функцией UBound. Для пустого массива она возвращает -1 (минус один). Из двух длин берётся меньшая. Минус один меньше чем длина массива (7.1.10226.0).  Значит, переменной smallerCount приравнивается значение -1. А дальше у нас идёт строка, на которой вылетает скрипт.

For count = 0 To smallerCount

Всё правильно, цикл от 0 до -1 не возможен в VBS. Поэтому и происходит ошибка. Починить скрипт довольно просто. Нужно поменять всего одну строку.

Было:

ElseIf (Left(OpsMgrVersion,3) = “6.1″) Then

Стало:

ElseIf ((Left(OpsMgrVersion,3) = “6.1″) or CInt (Left(OpsMgrVersion,1) >= 7)) Then

Что мы изменили? Теперь все версии SCOM 2012 и новее будут сравниваться с эталоном “6.1.7221.2″.  Запустим изменённый скрипт на сервере с установленным агентом SCOM, чтобы убедиться, что всё починилось.

C:\temp>cscript c:\temp\hotfix.vbs //nologo
<DataItem type=”System.PropertyBagData” time=”2014-05-30T10:46:47.2619294+04:00″ sourceHealthServiceId=”1D90D936-892E-0F5E-E342-150FAA500F42″><ConversionType>Alert</ConversionType><Property Name=”State” VariantType=”8″>GOOD</Property><Property Name=”KB Link” VariantType=”8″>http://go.microsoft.com/fwlink/?LinkID=167912</Property></DataItem>
Как видим, скрипт больше не вылетает по ошибке. К тому же он возвращает значение GOOD, то есть правильно определяет, что версия агента новее эталонной. Остались мелочи – экспортировать пакет управления, изменить скрипт и импортировать пакет управления обратно. Как это сделать, я описывал в предыдущих статьях.

Можно поступить проще. У нас используется SCOM2012, он заведомо новее эталонной версии, так что данный монитор для нас бесполезен. Давайте просто выключим его с помощью переопределения.