Мониторинг температуры процессора Windows-машины

Встала предо мною задача следить за температурой процессоров у рабочих станций, работающих под управлением ОС Windows.

Чтобы не изобретать велосипеда решил сначала изучить публикации в Интернете. Нашёл довольно много публикаций:

Всё очень хорошо… Казалось бы, бери и пользуйся, если бы одно, но серьёзное “но”… Точнее, несколько “но”.

“Но” первое. Практически во всех способах описывается случай, когда Zabbix-сервер и наблюдаемая машина расположены в одной локальной сети. Это мне не подходит, т.к. наблюдаемые мной машины разбросаны по обширной территории, многие машины расположены за NAT…

“Но” второе. Современные процессоры многоядерные, причём температурный датчик есть у каждого ядра, а найденные мной решения брали температуру у последнего найденного ядра  и считали именно это температурой процессора. Я посчитал. что это не честно. 🙂 Понимаю, что температура ядер одного процессора вряд ли будет различаться более, чем на 1-2 градуса, и такое решение имеет право на существование, но это дело принципа. 🙂 Считаю, что честнее вычислять среднее арифметическое температур ядер процессора, и правильнее именно это считать общей температурой.

“Но” третье. Хотелось получить решение как для однопроцессорных систем, так и для двухпроцессорных.

Итак, за основу решения берём публикацию https://habr.com/ru/post/228095/

Дополнительные вводные:

  1. В найденных мной решениях использовался Zabbix 2.x… Я же использую Zabbix 3.x и выше, что даёт дополнительные возможности. Например, активный клиент Zabbix может сам брать содержимое некоего текстового файла и отправлять его на  Zabbix-сервер для анализа.
  2. Хочется свести к минимуму дополнительную настройку уже имеющихся установленных zabbix-клиентов. Это даёт нам возможность создавать какие-то задачи в планировщике Windows, которые будут собирать нужные нам данные.

Итак, начинаю описывать решение. 🙂

Шаг 1.

Структура каталогов. Корневой каталог клиентской части у меня c:\zabbix . Этот каталог имеет следующую структуру

Т.е. всё, что будет касаться измерения температуры процессора, будет располагаться в каталоге C:\Zabbix\scripts\OHMR

Шаг 2.

В рабочий каталог положим файлы консольной версии Open Hardware Monotor:

  • OpenHardwareMonitorLib.dll
  • OpenHardwareMonitorReport.exe

Шаг 3.

Кладём в эту же папку наш скрипт, который будет при помощи Open Hardware Monotor определять температуру процессоров.

Я написал два практически равноценных варианта скриптов.

Вариант 1 – это VBS-скрипт

Кликните, чтобы увидеть текст OHMR.vbs

Option Explicit

‘********************************************************************
‘*
‘* Скрипт вычисления температуры процессора/процессоров компьютера
‘*
‘********************************************************************
Const ForWriting = 2

Dim strOHMRPath ‘ Путь к исполняемому файлу с OpenHardwareMonitorReport.exe
Dim WshShell
Dim WshExec
Dim TextStream
Dim Str
Dim MyDim
Dim strCPU0, strCPU1
Dim sum0, sum1, n0, n1

strOHMRPath = “C:\zabbix\scripts\OHMR\OpenHardwareMonitorReport.exe”
strCPU0 = “C:\zabbix\scripts\OHMR\cpu0.txt”
strCPU1 = “C:\zabbix\scripts\OHMR\cpu1.txt”

‘ Проверяем наличие исполняемого файла

if not MyFileExist (strOHMRPath) then
wscript.echo “Исполняемый файл OpenHardwareMonitorReport.exe ненайден…”
wscript.quit
end if

sum0 = 0
sum1 = 0
n0=0
n1=0

‘ Получаем ВСЕ данные StdOut OHMR и выделяем только нужные нам параметры
Set WshShell = CreateObject(“WScript.Shell”)

Set WshExec = WshShell.Exec(strOHMRPath )

WScript.Sleep 1000

Set TextStream = WshExec.StdOut

‘ Пока не достигли конца текста…
do While Not TextStream.AtEndOfStream

‘ Получаем очередную строку из результата работы команды
Str = Trim(TextStream.ReadLine())

‘ Убираем лишние пробелы из строки.
Do While Str <> Replace (str, ” “,” “)
Str = Replace (str, ” “,” “)
loop

‘ Если строка не нулевой длины, разбиваем её на составляющие и собираем данные по температуре…
if len (str) > 0 Then

If instr(Str,”:”) and instr(Str,”(/intelcpu/0/temperature/”) then
MyDim = split ( str, ” “)
n0 = n0 + 1
sum0 = sum0 + MyDim(8)
end if

If instr(Str,”:”) and instr(Str,”(/intelcpu/1/temperature/”) then
MyDim = split ( str, ” “)
n1 = n1 + 1
sum1 = sum1 + MyDim(8)
end if

End If

loop

Set TextStream = Nothing

Set WshExec = Nothing

Set WshShell = Nothing

‘ Записываем в файл температуру нулевого процессора
sum0 = cint(sum0/n0)
TextToFile strCPU0, sum0

‘ Записываем в файл температуру первого процессора
if n1>0 then
sum1 = cint(sum1/n1)
TextToFile strCPU1, sum1
else
if MyFileExist(strCPU1) Then MyDeleteFile strCPU1
end if

wscript.quit

‘********************************************************************
‘*
‘* Функция : MyFileExist
‘* Описание : Функция проверки существования файла
‘* Вход : Имя файла
‘* Выход : true, если файл существует, и false, если файл отсутствует.
‘*
‘********************************************************************
Function MyFileExist (ByVal FileName)
dim fso

On Error Resume Next

Set fso = WScript.CreateObject(“Scripting.FileSystemObject”)

MyFileExist = (fso.FileExists(FileName))

Set fso = Nothing

On Error Goto 0

end Function

‘********************************************************************
‘*
‘* Функция : MyDeleteFile
‘* Описание : Функция удаления файла
‘* Вход : Имя файла
‘* Выход :
‘*
‘********************************************************************
Function MyDeleteFile (ByVal FileName)
dim fso

On Error Resume Next

Set fso = WScript.CreateObject(“Scripting.FileSystemObject”)

MyDeleteFile = (fso.DeleteFile(FileName,true))

Set fso = Nothing

On Error Goto 0

end Function

‘********************************************************************
‘*
‘* Процедура : TextToFile
‘* Описание : Записывает в файл текстовую информацию
‘* Вход : strFileName – имя файла, в который нужно писать информацию
‘* strString – записываемая информация
‘*
‘********************************************************************
Sub TextToFile(ByVal strFileName, ByVal strString)

Dim fso, f

On Error Resume Next

Set fso = CreateObject(“Scripting.FileSystemObject”)
Set f = fso.OpenTextFile(strFileName, ForWriting, True)
f.WriteLine strString
f.Close
Set f = Nothing
Set fso = Nothing

On Error Goto 0

End Sub

Вариант 2 – это BAT-файл.

Кликните, чтобы увидеть текст ohmr.bat

@echo off

setlocal enabledelayedexpansion

rem Получим данные по 0-му процессору
set /a ssum=0
set /a n=0
set /a temper=0

for /F “usebackq tokens=1-10” %%a in (`C:\zabbix\scripts\OHMR\OpenHardwareMonitorReport.exe`) do (
echo “%%a %%b %%c %%d %%e %%f %%g %%h %%i %%j” | find “/intelcpu/0/temperature” | find “:”>nul
if !errorlevel! == 0 (
set /a ssum+=%%g
set /a n+=1
)
)

set /a temper=%ssum%/%n%

echo %temper% > C:\zabbix\scripts\OHMR\cpu0.txt

rem Получим данные по 1-му процессору

set /a ssum=0
set /a n=0
set /a temper=0

for /F “usebackq tokens=1-10” %%a in (`C:\zabbix\scripts\OHMR\OpenHardwareMonitorReport.exe`) do (
echo “%%a %%b %%c %%d %%e %%f %%g %%h %%i %%j” | find “/intelcpu/1/temperature” | find “:”>nul
if !errorlevel! == 0 (
set /a ssum+=%%g
set /a n+=1
)
)

if %n% gtr 0 (
set /a temper=!ssum!/!n!
echo !temper! > C:\zabbix\scripts\OHMR\cpu1.txt
)

exit

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

Шаг 4.

Указанные выше скрипты мы будем запускать каждые 5 минут при помощи планировщика Windows. Чтобы не создавать задание планировщика руками на каждом компьютере, я написал простенький батник, который создаёт за меня нужное задание.

Кликните, чтобы увидеть текст INSTALL_OHMR.bat

@echo off

rem Скрипт за пускается на Windows XP?
ver | find “5.1.”

If %errorlevel%==0 (
rem Windows XP
SCHTASKS /Create /RU “NT AUTHORITY\SYSTEM” /SC HOURLY /ST 00:00:00 /TN “OHMR” /TR “\”C:\Windows\System32\cscript.exe\” C:\Zabbix\scripts\OHMR\OHMR.vbs”
) else (
rem НЕ Windows XP
SCHTASKS /Create /RU “NT AUTHORITY\SYSTEM” /SC DAILY /ST 00:00 /RI 5 /DU 24:00 /TN “OHMR” /TR “\”C:\Windows\System32\cscript.exe\” C:\Zabbix\scripts\OHMR\OHMR.vbs” /RL HIGHEST /F
)

del /f /q C:\zabbix\scripts\OHMR\cpu0.txt
del /f /q C:\zabbix\scripts\OHMR\cpu1.txt

CALL C:\zabbix\scripts\OHMR\ohmr.bat

EXIT

Правда, созданное в Windows XP задание, нужно будет ручками подкрутить, иначе скрипт будет запускаться не каждые 5 минут, а каждый час. 🙂 Для меня это не важно, т.к. у меня в хозяйстве машин с Windows XP менее 5 штук…

Шаг 5.

Проверяем, что у вас в рабочем каталоге каждые 5 минут обновляется файл с именем cpu0.txt . Внутри этого файла содержится одно число, которое соответствует текущей температуре процессора.

Если у вас в компьютере установлено 2 процессора, то также должен будет появиться и обновляться каждые 5 минут файл с именем cpu1.txt

Шаг 6.

Создаём в Zabbix шаблон с подходящим именем. Свой шаблон я назвал Template OS Windows Workstations Active – CPU Temperature.

Тут ничего сложного нет… Мы просто создаём 2 элемента данных, которые содержат в себе текст из создаваемых скриптом файлов. В первом элементе данных мы используем ключ vfs.file.contents[C:\zabbix\scripts\OHMR\cpu0.txt] , а во втором элемиенте данных vfs.file.contents[C:\zabbix\scripts\OHMR\cpu1.txt]

Просто покажу скриншоты.

Шаг 7.

При необходимости создаём нужное количество триггеров. Например, таких

Также можно создать и график. Например, такой

Шаг 8.

Назначаем шаблон наблюдаемому компьютеру и ждём, когда начнут поступать собираемые данные…

И строится график…

Шаг 9.

Радуемся, что у нас всё работает. 🙂