На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов Хостинг

И есть ли в этом смысл?

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

Для тех, кто задумался и сомневается, я решил описать кое-что из своего опыта.

Мониторинг вообще штука полезная, бесспорно. У меня лично в какой-то период возникло сразу несколько задач:

  1. Круглосуточно и непрерывно мониторить одну специфическую железку по ряду параметров;

  2. Мониторить у рабочих станций информацию о температурах, ЦП в первую очередь;

  3. Всякие мелочи в связи с широким внедрением удалёнки: количество подключений по VPN, общее состояние дополнительных виртуальных машин.

Подробнее про локальные задачи:
  1. Надо было оценить и наглядно представить данные об интернет-канале. Канал на тот момент представлял собой 4G-роутер Huawei. Это устройство было последним, но далеко не первым в огромном количестве плясок с бубном в попытках избавиться от разного рода нестабильностей. Забегая вперёд: забирать с него данные напрямую о качестве сигнала более-менее стандартными средствами оказалось невозможно, и даже добраться до этих данных — отдельный квест. Пришлось городить дендрофекальную конструкцию, которая, на удивление стабильно, и стала в итоге поставлять данные. Данные в динамике и в графическом представлении оказались настолько неутешительными, что позволили убедить всех причастных таки поменять канал, даже и на более дорогой;

  2. Данные о температуре процессора дают сразу несколько линий: можно обнаружить шифровальщик в процессе работы, наглядно сделать вывод о недостаточной мощности рабочей станции, найти повод провести плановую чистку, узнать о нарушении условий эксплуатации. Последний пункт особенно хорош: множество отказов оборудования и BSOD’ов в итоге нашли причину в «я ставлю обогреватель под стол, ну и свой баул, ну да, прям к этой решётке. А что? А я канпуктер развернула, а то неудобно»;

Итак, нам понадобятся:

  1. Виртуальная машина или физический хост. Zabbix нетребователен к ресурсам при небольшом количестве хостов на мониторинге: мне хватило одного виртуального процессора на 2ГГц и 4 Гб RAM за глаза;

  2. Любой инструмент для автоматического раскидывания zabbix-agent. При некотором скилле это можно делать даже через оригинальный WSUS, или просто батником с psexec, вариантов много. Также желательно запилить предварительно сконфигурированный инсталлятор агента — об этом ниже;

  3. Много желания пилить напильником. Скажу честно и сразу: из первоначального списка 3 из 3 реализовывалось руками на местности. Zabbix стандартной комплектации в такое не может.

У Zabbix много вариантов установки. В моём случае (я начинал с 4 LTS) сработала только установка руками в чистую, из собственного образа, OC в виртуальной машине на Hyper-V. Так что, коли не получится с первого раза, — не сдавайтесь, пробуйте. Саму процедуру подробнее описывать не буду, есть куча статей и хороший официальный мануал.

Вот так красиво это выглядит, когда применяется по назначению. Автор: Dotneft - собственная работа, CC BY-SA 4.0 https://commons.wikimedia.org/w/index.php?curid=73459928
Вот так красиво это выглядит, когда применяется по назначению. Автор: Dotneft — собственная работа, CC BY-SA 4.0 https://commons.wikimedia.org/w/index.php?curid=73459928

Про формирование инсталлятора агента: один из самых простых способов — использовать утилиты наподобие 7zfx Builder . Нужно будет подготовить:

  • файл zabbix_agentd.conf ;

  • скрипт инсталлятора с кодом наподобие этого:

SETLOCAL ENABLEDELAYEDEXPANSION 
SET INSTDR=C:\Zabbix\Agent 
SET IP=192.168.100.10 
set ip_address_string="IPv4-адрес"

for /f "usebackq tokens=2 delims=:" %%F in (ipconfig ^| findstr /c:%ip_address_string%) do SET IP=%%F 
SET IP=%IP: =% 
ECHO SourceIP=%IP%>> "%INSTDR%\conf\zabbix_agentd.conf" 
ECHO ListenIP=%IP%>> "%INSTDR%\conf\zabbix_agentd.conf" 
ECHO Hostname=%COMPUTERNAME%>> "%INSTDR%\conf\zabbix_agentd.conf"

"%INSTDR%\bin\zabbix_agentd.exe" -c "%INSTDR%\conf\zabbix_agentd.conf" -i 
net start "Zabbix Agent" 
ENDLOCAL

Кстати, об IP. Адрес в Zabbix является уникальным идентификатором, так что при «свободном» DHCP нужно будет настроить привязки. Впрочем, это и так хорошая практика.

Также могу порекомендовать добавить в инсталлятор следующий код:

sc failure "Zabbix Agent" reset= 30 actions= restart/60000

Как и многие сервисы, Zabbix agent под Windows при загрузке ОС стартует раньше, чем некоторые сетевые адаптеры. Из-за этого агент не может увидеть IP, к которому должен быть привязан, и останавливает службу. В оригинальном дистрибутиве при установке настроек перезапуска нет.

После этого добавляем хосты. Не забудьте выбрать Template – OS Windows. Если сервер не видит клиента — проверяем:

  1. файрвол на клиенте;

  2. работу службы на клиенте — смотрим zabbix_agentd.log, он вполне информативный.

# -*- coding:utf-8 -*-

Import XML configuration files using Zabbix API.

Detailed information about zabbix templates import/export using the

Zabbix Web-UI and Zabbix API usage for import configurations,

# for handling file encoding in python2

# Number of displayed element values per line (on help description)

# Parse command line arguments

‘Zabbix exported template xml file’

‘variable.One of the two methods is required. ‘

‘In case you are using both,the flag value takes ‘

‘precedence over the environment variable’

‘Use the —passwd flag to provide the Zabbix API password.’

‘Alternatively you can set the ZABBIX_API_PASSWD environment ‘

‘variable.One of the two methods is required. ‘

‘In case you are using both,the flag value takes ‘

‘precedence over the environment variable’

‘All the elements in the xml file that are missing in the zabbix’

‘database are being created by default.To unselect the ‘

‘ by a list of space separated values to be excluded.The ‘

‘provided, all of them will be excluded for thecreateMissing ‘

‘All the elements in the xml file that already exists in the ‘

‘zabbixdatabase are being updated by default.To unselect the ‘

‘by a list of space separated values to be excluded.The ‘

‘provided, all of them will be excluded for theupdateExisting ‘

‘All the elements that existes in the zabbix database that are ‘

‘notpresent in the xml file are being preserved by default.’

‘To select the deleteMissing option (i.e set true), use this flag’

‘provided, all of them will be included for thedeleteMissing ‘

# Convert to string and then to byte

# Get string

# Convert to object

# TODO: add API version check

# Get authentication token

# If authentication was not OK

# Read template file content

# Set import parameters, including template file content

‘SUCCESS: configuration import’

# in case the respective argument is missing:

# Logout to prevent generation of unnecessary open sessions

Пример данных для 1 диска

Код: Выделить всё

{
"hddList":{
"hdd":{
"id":"2",
"hddName":"hdd2",
"hddPath":"",
"hddType":"SATA",
"status":"ok",
"capacity":"5723166",
"freeSpace":"1714176",
"property":"RW"
}}}

Код: Выделить всё

{
"hddList":{
"hdd":[
{
"id":"1",
"hddName":"hdda",
"hddPath":"",
"hddType":"SATA",
"status":"ok",
"capacity":"5723166",
"freeSpace":"0",
"property":"RW"
},
{
"id":"2",
"hddName":"hddb",
"hddPath":"",
"hddType":"SATA",
"status":"ok",
"capacity":"5723166",
"freeSpace":"0",
"property":"RW"
}
]}}
Предобработка JS обнаружение дисков
Предобработка JS обнаружение дисков

Код: Выделить всё

var data = JSON.parse(value);
var out = [];

  data.hddList.hdd.forEach(function (field) {
   out.push({
     "{#HDD_ID}": field.id,
     "{#HDD_NAME}": field.hddName,
     "{#HDD_PATH}": field.hddPath,
     "{#HDD_TYPE}": field.hddType
            });
  })

//return JSON.stringify(out);
// Читаемый вид перенос строк              
return JSON.stringify(out).replace(/\[/g,"[\n").replace(/\},/g,"},\n").replace(/\}]/g,"}\n]");
Предобработка JS обнаружение дисков результат
Предобработка JS обнаружение дисков результат

Второй вариант скрипта Предобработки

Код: Выделить всё

var data = JSON.parse(value);
var out = [];
var masd = "";

//data.hddList.hdd = data.hddList.hdd.map((padObj) => Object.assign({}, padObj, {hdd: [padObj.hdd]}));

// Получим список типов дисков hdd ssd облако и тд
for (var typeofdisk in data.hddList) {

  var test = data.hddList.hdd
test.forEach(function (key) {

// Получим данные для типа диска
   out.push({
     "{#HDD_ID}": key.id,
     "{#HDD_NAME}": key.hddName,
     "{#HDD_PATH}": key.hddPath,
     "{#HDD_TYPE}": key.hddType
         });
 // Одной строкой
 //    out.push({"{#HDD_ID}": key.id,"{#HDD_NAME}": key.hddName,"{#HDD_PATH}": key.hddPath,"{#HDD_TYPE}": key.hddType});
})}
//masd+= out;

//return JSON.stringify(out);
// Читаемый вид перенос строк              
return JSON.stringify(out).replace(/\[/g,"[\n").replace(/\},/g,"},\n").replace(/\}]/g,"}\n]");
//return JSON.stringify(masd).replace(/\[/g,"[\n").replace(/\},/g,"},\n").replace(/\}]/g,"}\n]");

Код: Выделить всё

var out = [];
for (var i = 0; i < 3; i++) {
    var objekt = {};
    objekt['{#HDD_ID}'] = 2;
    objekt['{#HDD}'] = 'hdd';
    objekt['{#HDD_NAME}'] = 'hdd' + i;
    objekt['{#HDD_NAME}'] = '';
    objekt['{#HDD_TYPE}'] = 'SATA';
    out.push(objekt);;
}

return JSON.stringify(out);

Инфо о json-stringify

Код: Выделить всё

var data = JSON.parse(value);
var out = [];
var masd = "";

// Получим список типов дисков hdd ssd облако и тд
for (var typeofdisk in data.hddList) {

  var test = data.hddList.hdd
var out = [];
for (var i = 0; i < 3; i++) {
    var objekt = {};
    objekt['{#HDD_ID}'] = 2;
    objekt['{#HDD}'] = 'hdd';
    objekt['{#HDD_NAME}'] = 'hdd' + i;
    objekt['{#HDD_NAME}'] = '';
    objekt['{#HDD_TYPE}'] = 'SATA';
    out.push(objekt);;
}}

return JSON.stringify(out);

Пятый Вариант Скрипта
Входные данные

Код: Выделить всё

{ "hddList":{
"hdd":
{ "id":"2", "hddName":"hdd2", "hddPath":"", "hddType":"SATA", "status":"ok", "capacity":"5723166", "freeSpace":"1714176", "property":"RW" }, 
"hdd":
{ "id":"3", "hddName":"hdd3", "hddPath":"", "hddType":"SATA", "status":"ok", "capacity":"5893165", "freeSpace":"3717179", "property":"RW" },
"ssd":
{ "id":"4", "hddName":"hdd4", "hddPath":"", "hddType":"SATA", "status":"ok", "capacity":"89359", "freeSpace":"5479215", "property":"RS" }
}}

Код: Выделить всё

const myJson = value
const re = new RegExp(/([^"]+)"\s{0,}:\s{0,}{\s{0,}"id"/, 'gim');

var count = 0;
result = myJson.replace(re, function(match) {
        count++;
        return count + "_" + match;
    })
    data = JSON.parse(result),
    massiv = [];

for ( key in data.hddList) {
    massiv.push(data.hddList[key]);
}

return JSON.stringify(massiv);

Эксперименты ко Второму варианты

Код: Выделить всё

var data = JSON.parse(value);
var out = [];
var masd = "";
var dataout = "";

// Получим список типов дисков hdd ssd облако и тд
for (var typeofdisk in data.hddList) {
// Накопительная переменная, диски
dataout+= typeofdisk+"\n";
}
return dataout;

Эксперимент с данными виде текста не json

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем Диск + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"/gmi);

// Найдем все ID
var regexp = diskval.match(/"[A-Za-z0-9]+":{"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("" + regexp).split(',');
//for (var i = regexp.length - 1; i >= 0; --i) 
for (var i = 0; i < myarray.length; i++){
    //var idn = (myarray[i]).replace(/\[|]/gi, '');
    var idn = "\"id\":\"\d+\""
    // console.log(myarray[i], myarray[i].match(/"id":"(\d+)"/gmi));
    var res = myarray[i].match(/"id":"(\d+)"/);
    // если нашли число
    if ( res[1] >= 0 ) {
        // удаляем данные об ИД и добавялем ИД к названию диска
        myarray[i] = myarray[i].replace(/:{"id":"(\d+)"/, "").replaceAll("\"", "");

        //выводим имя диска в консоль:
        console.log(myarray[i]);
        //выводим ид диска в консоль
        console.log(res[1]);
    }
}

Метод str.match(regexp), если у регулярного выражения regexp
нет флага g, ищет первое совпадение и возвращает его в виде массива:

Читайте также:  Упрощение выбора: поиск идеальной версии PHP для WordPress

Далее будем работать с такими данными
Тестовые данные

Код: Выделить всё

{
"hddList":{
"hdd":{
"id":"2",
"hddName":"hdd2",
"hddPath":"",
"hddType":"SATA2",
"status":"ok",
"capacity":"5723166",
"freeSpace":"1714176",
"property":"RW"
},
"hdd":{
"id":"3",
"hddName":"hdd3",
"hddPath":"",
"hddType":"SATA3",
"status":"ok",
"capacity":"5893165",
"freeSpace":"3717179",
"property":"RW",
"id":"5",
"hddName":"hdd5",
"hddPath":"",
"hddType":"SATA5",
"status":"ok",
"capacity":"893559",
"freeSpace":"54759215",
"property":"RS5"
},
"ssd":{
"id":"4",
"hddName":"hdd4",
"hddPath":"",
"hddType":"SATA4",
"status":"ok",
"capacity":"89359",
"freeSpace":"5479215",
"property":"RS"
}}}

Начало разработки тестируем

Код: Выделить всё

// Найдем все ID
var regexp = value.match(/"id":"[0-9]+"/gmi);
// запятую заменим на перенос строк
//var test = ("[" + regexp + "]").replace(/\,/g,"\n");
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i) 
for (var i = 0; i < myarray.length; i++){
//var idn = (myarray[i]).replace(/\[|]/gi, '');
var idn = "id\":\"3\"";
// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем название дисков
test = diskval.match(new RegExp(([A-z]+)":{" idn,'gim'));
return test

//return listdis ;
}

СРАЗУ НУЖНЫЙ БЛОК С ДИСКОМ

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем Диск + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"|"id":"[0-9]+"/gmi);
// Найдем все ID
var regexp = diskval.match(/"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i) 
for (var i = 0; i < myarray.length; i++){
//var idn = (myarray[i]).replace(/\[|]/gi, '');
var idn = "\"id\":\"2\""
// Выберем название дисков
testx = "[" + diskid + "]";
test = testx.match(/[A-z0-9.]+/g,"");
//.match(new RegExp(idn,'gim'));
return testx
//return listdis ;
}

Выведем ID и Тип Диска который перед ID

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем Диск + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"|"id":"[0-9]+"/gmi);

// Найдем все ID
var regexp = diskval.match(/"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i) 
for (var i = 0; i < myarray.length; i++){
//var idn = (myarray[i]).replace(/\[|]/gi, '');

// Выберем название дисков, для соответствующего ID ,с фиксированными переменными ID
diskids = "[" + diskid + "]";
//test = diskids.match(/[A-z0-9.]+/g,"");
//.match(new RegExp(idn,'gim'));
// Формирование регулярного выражения с текущим ID
var idn = "\"([A-z0-9.]+)\":{|\"id\":\"5\""
// Текущее ID с названиям дисков
namediskid =diskids.match(new RegExp(idn,'gim'));
namediskids ="[" + namediskid + "]"
// Формирование регулярного выражения с текущим ID
var idx = "\"([A-z0-9.]+)\":{,\"id\":\"5\""
// Имя диска и текущий ID
nameid =namediskids.match(new RegExp(idx,'gim'));
nameids = "[" + nameid + "]";
// Оставляем только Имя диска
hddName =nameids.match(/"(([A-z0-9.]+))":{/im);
return hddName[1];
}

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"");
// Выберем Диск + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"|"id":"[0-9]+"/gmi);

// Найдем все ID
var regexp = diskval.match(/"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i)
for (var i = 0; i < myarray.length; i++){
var idv = (myarray[i]).replace(/\[|]/gi, '').replace(/"/gi,"\\\"");
var res = myarray[i].match(/"id":"(\d+)"/);

// Выберем название дисков, для соответствующего ID
diskids = "[" + diskid + "]";
// Формирование регулярного выражения с текущим ID
var idn = '\"([A-z0-9.]+)\":{|'+idv+''

//var idn = "\"([A-z0-9.]+)\":{|\"id\":\"${res[1]}\""
// Текущее ID с названиям дисков
namediskid =diskids.match(new RegExp(idn,'gim'));
namediskids ="[" + namediskid + "]"
// Формирование регулярного выражения с текущим ID
var idx = '\"([A-z0-9.]+)\":{,'+idv+''
//var idx = "\"([A-z0-9.]+)\":{,\"id\":\"${res[1]}\""
// Имя диска и текущий ID
nameid =namediskids.match(new RegExp(idx,'gim'));
nameids = "[" + nameid + "]";
// Оставляем только Имя диска
DiskListName =nameids.match(/"(([A-z0-9.]+))":{/im);
var DiskList =DiskListName[1];
return DiskList;
}

И ГОТОВЫЙ ВАРИАНТ СКРИПТА

Код: Выделить всё

// Данные одной строкой
var diskval = value.replace(/[\n\r]+/g,"").replace(/[\[\]]+/g,"");
// Выберем Вид Диска + ID
var diskid = diskval.match(/"([A-z0-9.]+)":{"id":"[0-9]+"|"id":"[0-9]+"/gmi);

// Переменные
var sep="";
var dataout = "";

// Найдем все ID
var regexp = diskval.match(/"id":"[0-9]+"/gmi);
// Разделитель запятая, для цикла
var myarray = ("[" + regexp + "]").split(',');
//for (var i = regexp.length - 1; i >= 0; --i)
for (var i = 0; i < myarray.length; i++){
// Подстановка ID в регулярку
var idv = (myarray[i]).replace(/\[|]/gi, '').replace(/"/gi,"\\\"");
// ID
var ID = idv.match(/([0-9]+)/gmi)

// Выберем Вид дисков, для соответствующего ID
diskids = "[" + diskid + "]";
// Текущее ID с видом дисков, регулярного выражения с текущим ID
viddiskid =diskids.match(new RegExp('\"([A-z0-9.]+)\":{|'+idv+'','gim'));
viddiskids ="[" + viddiskid + "]"
// Вид диска и текущий ID, регулярного выражения с текущим ID
vidid =viddiskids.match(new RegExp('\"([A-z0-9.]+)\":{,'+idv+'','gim'));
vidids = "[" + vidid + "]";
// Оставляем только Вид диска
DiskListVid =vidids.match(/"(([A-z0-9.]+))":{/im);
// Вид диска
var DiskList =DiskListVid[1];
// Имя Диска
var diskname =diskval.match(new RegExp('\"id\":\"'+ID+'\",\"hddName\":\"([A-z0-9.]+|)\"','im'));
// Путь Диска
var diskpath =diskval.match(new RegExp('\"id\":\"'+ID+'\".*?,\"hddPath\":\"([A-z0-9.]+|)\"','im'));
// Тип Диска
var disktype =diskval.match(new RegExp('\"id\":\"'+ID+'\".*?,\"hddType\":\"([A-z0-9.]+|)\"','im'));
// Строка с данными
sop=''+sep+'{"{#HDD_ID}": "'+ID+'", "{#DISKLIST}": "'+DiskList+'", "{#HDD_NAME}": "'+diskname[1]+'", "{#HDD_PATH}": "'+diskpath[1]+'", "{#HDD_TYPE}": "'+disktype[1]+'"}';
var sep=",";
// Накопительная переменная для цикла
dataout+= sop;
}
// Добавим скобки массива, для объекта
out = "[" + dataout + "]";
//return out;
// Читаемый вид перенос строк              
return out.replace(/\[/g,"[\n").replace(/\},/g,"},\n").replace(/\}]/g,"}\n]");

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессовArturs Lontons
Zabbix Certified Expert & Trainer

What are the different ways you can use Zabbix preprocessing and why you should consider implementing it in your environment? Let’s take a brief look at how Zabbix preprocessing has evolved and the technical nuances of transforming and storing your preprocessed data.

Contents

I. Introduction (1:00:56)
II. Evolution of preprocessing (1:01:43)
III. The many ways of preprocessing (1:04:34)
IV. Preprocessing under the hood (1:17:44)

Introduction

Why do we need preprocessing? Let’s say we’re retrieving a lot of data in freeform, which is not fit for calculations, aggregations, or optimal data storage.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

For us to  be able to aggregate this data and to optimize the data storage, it first must be preprocessed. And that’s what Zabbix provides, from preprocessing simple text to integration with Prometheus exporters in Zabbix 4.2 and CSV to JSON transformation in Zabbix 4.4, etc.

Evolution of preprocessing

Let’s take a look at where we began and where we are now.

Before Zabbix 3.4, the legacy preprocessing functionality was limited to:

  • custom multipliers,
  • numeral system transformations (boolean, hex, etc.), and
  • delta calculations (simple changes/speed per second).

If you required more elaborate data transformations, you had to transform the data with other tools, for example – write your own scripts in Python, PHP, etc. to preprocess the data. But over time the Zabbix preprocessing functionality has evolved. What has changed?

The preprocessing tab as you all currently know it was added in Zabbix 3.4. It also introduced a variety of new approaches to transform the data before storing it in the database:

  • regular expressions,
  • simple trims,
  • XPath and JSONPath support.

Over time Zabbix preprocessing evolved even further and extended the functionality in Zabbix 4.2. This version added even more new ways to preprocess the data:

  • JavaScript and Prometheus exporter support,
  • validation rules — to validate the data that you currently have,
  • throttling — to discard unnecessary data,
  • custom error handling — for additional human readability,
  • preprocessing support by the Zabbix proxy — to offload the performance overhead from the Zabbix server to the Zabbix proxy, thus adding a lot more flexibility when it comes to scaling your zabbix instance up even further.

Zabbix 4.4, which is completely fresh at this point, improved on preprocessing functionality even more and introduced:

  • XML data preprocessing via XPath,
  • JSONPath aggregation and search,
  • extended custom error handling,
  • CSV to JSON preprocessing,
  • WMI, JMX, and ODBC data collection to JSON arrays enabling preprocessing via JSONPath.

The many ways of preprocessing

Let’s have a look at the preprocessing methods, starting with the simpler ones.

Text preprocessing – a value is retrieved using a regular expression, and then it’s transformed from text, and stored as a number. If needed, we can, for example, trim a value and store it as a regular number.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Zabbix is also able to preprocess XML and JSON Structured data. XML XPath can be used for aggregations or calculations of XML data. The same can be done with JsonPath in Zabbix 4.4.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Numeric data can be transformed with custom multipliers. It means data can be multiplied by an X amount, for example, to transform bytes to bits. For division, use decimal numbers with zero before the dot, as in the example.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Delta calculations can be used to count simple changes, such as the difference between the current and the previous values, and change per second.

Next, we are going to look into the preprocessing methods added in Zabbix 4.2, such as JavaScript support.

JavaScript is implemented in Zabbix using the Duktape engine. It enables many different approaches to preprocessing— the limit is your imagination and your scripting skills. With JavaScript you can perform:

  • data transformation,
  • data aggregation,
  • data filtering,
  • logical expressions, etc.

For example, Raw diskstats output is not very usable by Zabbix without transforming the data to JSON.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Convert diskstats to JSON

The initial data is unreadable, and you need the script to make it work.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Once the JSON script is specified, it will split the diskstats data and transform it into JSON, and then the data can be used in LLD to create items.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Preprocessed data ready for LLD

The items in the example below were created with the corresponding metrics via JavaScript.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

As for validation rules, they were introduced because custom validation logic was required. For example, if a temperature sensor fails, and we receive out-of-range temperature data, it should be discarded or an error message should be displayed.

Читайте также:  Question Samsung EVO uses Secret Non-Industry Standard for “Wear Leveling Count”

With validation rules, we can check if:

  • the value is in range,
  • the value matches the defined regular expression,
  • the value does not match the defined regular expression,
  • We can check if there are errors in JSON/XML or we can look for errors by using regex.

In case the preprocessing fails, custom behavior can be defined:

  • discard the value completely,
  • set value to X,
  • set error to X.

For example, the value outside of the defined range from −100 to 100 will be discarded and not stored in the database.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Discarding the value outside of the defined range

A matched regular expression is used in the example below to check for ups and downs in the values.  In case of different service status, the value will be set to ‘Unknown’, and a trigger will fire.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Matching a regular expression

It is also possible to check for application-level error messages in JSONPath, XPath or regular expressions.

In my example, I have a check for the ErrorMessage field in JSON. If it contains data, the error message will be displayed, otherwise our data contains no errors.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Next up, Zabbix 4.2 also introduced throttling. It helps to improve performance and save database space, especially in high-frequency monitoring as it ensures minimal performance impact. This is very useful when we retrieve a lot of duplicate data at a very high frequency as in the case of industrial hardware.

In this example, data is gathered every two seconds — you just don’t want to store it as text without preprocessing. The repeating ups and downs can be ignored, and the value is just stored when it changes.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Or, a heartbeat can be defined. The data will be discarded by default and stored at the heartbeat frequency, for example, every 30 seconds.

I have some very basic examples — essentially, the same ups and downs but transformed into numbers. Data is gathered every two seconds, and before throttling was introduced, all 0 and 1 used to be stored.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

With throttling in Zabbix 4.2, all repeated values are discarded to save a lot of space.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Triggers will fire because data has been discarded for the past 30 minutes or so but the service has been up, unless a heartbeat is enabled. A heartbeat can help avoiding no data triggers misfiring, which can be caused by a throttling rule without a heartbeat.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессовThrottling with a heartbeat

This works with everything: text files, log files, repeating text service status messages, etc. Throttling will discard all of that repeating data and just store it on heartbeats.

Starting with Zabbix 4.2Prometheus exporters are supported. It’s yet another powerful function with an unimaginable amount of use cases:

  • query Prometheus endpoint with HTTP checks;
  • preprocessing to obtain metrics;
  • LLD to discover components monitored by Prometheus, etc.

Prometheus exporters have a lot of custom integrations — either official or from community providers — that expose metrics of different systems:

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

What if I want to integrate my custom exporters with Zabbix? I can use Prometheus exporter data with a proper preprocessing rule and push that data into Zabbix.

To do that, use the Prometheus pattern preprocessing rule:

  1. Create a master HTTP item pointed towards the Prometheus agent — to gather all data via the HTTP item.
  2. Create dependent items with Prometheus pattern and retrieve the specific metric.

You can either receive a specific metric or a label value.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

It can be even more elegant. We can use Prometheus to create a dependent item LLD with a preprocessing step to transform Prometheus to JSON and then use LLD.

In my example, I have a Prometheus to JSON preprocessing rule to grab all data on the time a specific CPU spent in a specific mode, for all modes for all of the CPUs.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Here is the JSON data retrieved.На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Once the LLD rule is set up, I can define my item prototype with the Prometheus pattern preprocessing step and plug the macros in for automatic discovery across all the CPUs and all the modes.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

As you can see, I have all of my CPUs for all of my modes discovered.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Here are the results from my default Prometheus agent. Remember that there are a lot of custom Prometheus exporters that can be integrated with databases, web servers, etc. If you are feeling really handy you can write your own Prometheus exporter to expose the data of your systems and then monitor them by Zabbix in a centralized manner.

Here are the values showing the time spent in a specific mode. You can see it is all working on a real virtual machine.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Before Zabbix 4.2, raw data was obtained from proxies. Proxies were getting raw data, compressing it, and sending it to the server where the data was preprocessed and then stored in the database.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Starting with Zabbix 4.2, proxies are doing the preprocessing.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессовThis update has a great performance benefit. You can scale up immensely with this overhead removed from the server and moved to the proxies.

Preprocessing under the hood

Preprocessing workflow

Now let’s have a look at how Zabbix treats preprocessing when it comes to Zabbix internal processes.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Zabbix preprocessing workflow

First, there is the preprocessing manager. It is the process introduced in Zabbix 3.4 which defines the preprocessing pattern.

  1. The preprocessing manager passes the values and stores them in the first-in-first-out queue.
  2. Once a value is stored in the queue, the manager checks if any preprocessing workers, which can be defined in the server config file, are free.
  3. All of the preprocessing tasks are assigned to a specific preprocessing worker so it does the preprocessing.
  4. Once the preprocessing worker has executed all the tasks, the value is passed back to the preprocessing manager and stored in the queue again.
  5. If there is no more preprocessing to be done, the data will be transformed to the specified data type (number, string, float, etc.) and stored in the database.

To define the value of preprocessing workers, use the StartPreprocessors parameter in the server configuration file. The number of workers is flexible and very much depends on how complex the preprocessing is, which is on the number of preprocessable items and preprocessing steps. Also, keep in mind that data gathering processes also directly influence the performance.

Preprocessing possibilities

To sum it up, here are the four pillars of preprocessing —why you should consider using it and what kind of benefits it can offer for your environment.

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Thank you! I hope this was helpful and you’ll have fun preprocessing in Zabbix 4.2 and 4.4.

See also: Presentation slides

Что доделывать?

Оооо. Ну, хотел повелосипедить, так это всегда пожалуйста. Прежде всего, нет алертов на события типа «критические» из системного лога Windows, при том, что механизм доступа к логам Windows встроенный, а не внешний, как Zabbix agent active. Странно, ну штош. Всё придётся добавлять руками.

Например

для записи и оповещения по событию «Система перезагрузилась, завершив работу с ошибками» (Microsoft-Windows-Kernel-Power, коды 41, 1001) нужно создать Item c типом Zabbix agent (active) и кодом в поле Key:

eventlog[System,,,,1001]

По этому же принципу создаём оповещения на другие коды. Странно, но готового template я не нашёл.

^RemoteRegistry|MMCSS|gupdate|SysmonLog|
clr_optimization_v.+|clr_optimization_v.+|
sppsvc|gpsvc|Pml Driver HPZ12|Net Driver HPZ12|
MapsBroker|IntelAudioService|Intel\(R\) TPM Provisioning Service|
dbupdate|DoSvc|BITS.*|ShellHWDetection.*$

И он не работает работает с задержкой в 30 дней.

После добавления служб в фильтр триггеры будут висеть ещё 30 дней. Этот срок, впрочем, тоже можно настроить
После добавления служб в фильтр триггеры будут висеть ещё 30 дней. Этот срок, впрочем, тоже можно настроить

Про службы, автоматически генерируемые в Windows 10, я вообще промолчу.
Нет никаких температур (но это, если подумать, ладно уж), нет SMART и его алертов (тоже отдельная история, конечно). Нет моих любимых UPS.

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

Читайте также:  Shared hosting Cpanel что это такое - и нужен ли он вам!? | Sprintsite

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

После допиливания – примерно так
После допиливания – примерно так

Что видно сразу, без настроек?

Сразу видно, что Zabbix заточен под другое 🙂 Но и об обычных рабочих станциях в конфигурации «из коробки» можно узнать много: идёт мониторинг оперативной памяти и SWAP, места на жёстких дисках, загрузки ЦП и сетевых адаптеров; будут предупреждения о том, что клиент давно не подключался или недавно перезагружен; агент автоматически создаёт список служб и параметров их работы, и сгенерирует оповещение о «необычном» поведении. Практически из коробки (со скачиванием доп. template’ов с офсайта и небольшой донастройкой) работает всё, что по SNMP: принтеры и МФУ, управляемые свитчи, всякая специфическая мелочь. Иметь алерты по тем же офисным принтерам в едином окне очень удобно.

О локальных задачах

Всё, что не встроено в Zabbix agent, реализуется через механизм Zabbix agent (active). Суть проста: пишем скрипт, который будет выдавать нужные нам данные. Прописываем наш скрипт в conf:

UserParameter=имя.параметра,путь\к\скрипту 
  • если хотите получать в Zabbix строку на кириллице из cmd — не надо. Только powershell;

  • если параметр специфический – для имени нужно будет придумать и сформулировать дерево параметров, наподобие «hardware.huawei.modem.link.speed» ;

  • отладка и стабильность таких параметров — вопрос и скрипта, и самого Zabbix. Об этом дальше.

Хотелка №1: температуры процессоров рабочих станций

В качестве примера реализуем хотелку «темература ЦП рабочей станции». Вам может встретиться вариант наподобие:

wmic /namespace:\root\wmi PATH MSAcpi_ThermalZoneTemperature get CurrentTemperature

но это не работает (вернее, работает не всегда и не везде).
Самый простой способ, что я нашёл — воспользоваться проектом OpenHardwareMonitor. Он свои результаты выгружает прямо в тот же WMI, так что температуру получим так:

@echo OFF 
SETLOCAL ENABLEDELAYEDEXPANSION 
SET TMPTMP=0 
for /f "tokens=* skip=1 delims=" %%I in ('wmic /namespace:\root\OpenHardwareMonitor PATH Sensor WHERE Identifier^="/intelcpu/0/temperature/1" get Value') DO (     
	SET TMPTMP=%%I && GOTO :NXT 
) 
:NXT  
ECHO %TMPTMP% 
ENDLOCAL 
GOTO :EOF

Конечно, при условии, что OHM запущен. В текущем релизе OHM не умеет работать в качестве Windows service. Так что придётся либо смущать пользователей очередной иконкой в трее, либо снова городить свой инсталлятор и запихивать OHM в сервисы принудительно. Я выбрал поcледнее, создав инсталляционный cmd для всё того же 7zfx Builder наподобие:

nssm install OHMservice "%programfiles%\OHM\OpenHardwareMonitor.exe" 
timeout 3 
net start "OHMservice" 
del nssm.exe /Q
  1. NSSM — простая и достаточно надёжная утилита с многолетней историей. Применяется как раз в случаях, когда ПО не имеет режима работы «сервис», а надо. Во вредоносности утилита не замечена;

  2. Обратите внимание на «intelcpu» в скрипте получения температуры от OHM. Т.к. речь идёт о внедрении в малом офисе, можно рассчитывать на единообразие парка техники. Более того, таким образом лично у меня получилось извлечь и температуру ЦП от AMD. Но тем не менее этот пункт требует особого внимания. Возможно, придётся модифицировать и усложнять инсталлятор для большей универсальности.

Работает более чем надёжно, проблем не замечено.

Хотелка № 2: получаем и мониторим температуру чего угодно

Понадобятся нам две вещи:

  1. Штука от братского китайского народа: стандартный цифровой термометр DS18B20, совмещённый с USB-UART контроллером. Стоит не сказать что бюджетно, но приемлемо;

param($cPort='COM3')

$port= new-Object System.IO.Ports.SerialPort $cPort,9600,None,8,one

$port.Open()
$tmp = $port.ReadLine()
$port.Close()

$tmp = $tmp -replace "t1="
if (([int]$tmp -lt 1) -or ([int]$tmp -gt 55)){

	#echo ("trigg "+$tmp)
	$port.Open()
	$tmp = $port.ReadLine()
	$port.Close()

	$tmp = $tmp -replace "t1="
} 
echo ($tmp)

Связка работает достаточно надёжно, но есть интересный момент: иногда, бессистемно, появляются провалы или пики на графиках:

На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов
На практике в небольшом офисе инфраструктура на операционной системе Windows не нужна. Удобная база данных для мониторинга abbix позволяет лучше оценивать состояние процессов

Тесты показали, что проблема в самом Zabbix, а данные с китайских датчиков приходят верные. Детальное рассмотрение пиков и провалов выявило неожиданный факт: похоже Zabbix иногда получает и/или записывает в БД не полное значение, а «хвост». Т.е., например, 1.50 от значения 21.50. При этом положение точки не важно — может получить и 1.50, и 50, и даже 0. Как так происходит, мне выяснить пока не удалось. Изменение timeout на поведение не влияет никак, ни в большую, ни в меньшую сторону.
Наверное, стоило бы написать багрепорт. Но уже вышел 6.0 LTS (у меня 5) и обновляться в текущей ситуации, пожалуй, не буду.

Хотелка № 3: OpenVPN подключения

Template’ов для OpenVPN и Zabbix существует довольно много, но все они реализованы на том или ином sh под *nix’ы . В свою очередь, «dashboard» OpenVPN-сервера представляет из себя, по сути, вывод утилиты в консоль, который пишется в файл по событиям. Мне лень было считать трафик по отдельным пользователям и вообще делать их discover, т.к. подключений и пользователей немного. Ограничился текущим количеством подключений:

$openvpnLogPath = "C:\OpenVPN\config\"
$openvpnLogName = "openvpn-status.log"

try { 
	$logData = Get-Content $openvpnLogPath$openvpnLogName -ErrorAction Stop
}
catch{
	
	Write-Host("Missing log file")
	exit 1
}

$logHeader = "OpenVPN CLIENT LIST"
$logHeader2 = "Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since"
$logMark1 = "ROUTING TABLE"

if ($logData[0] -ne $logHeader -or $logData[2] -ne $logHeader2 ){
	
	Write-Host("Bad log file")
	exit 1
}

$i = 0
foreach ($tmpStr in ($logData | select -skip 3)) {
	
	if ($tmpStr -eq $logMark1) {break}
	$i++
}

Write-Host($i)
exit 0

Хотелка № 4: спецжелезка 1

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

Боли лирическое отступление

установив один из таких темплейтов, я узнал, что «нормальная рабочая» температура чипа RAID-контроллера в серваке — 65+ градусов. Это, в свою очередь, побудило внимательнее посмотреть и на контроллер, и на сервер в целом. Были найдены косяки и выражены «фи»:

  1. Apaptec’у – за игольчатый радиатор из неизвестного крашеного силумина высотой чуть более чем нихрена, поток воздуха к которому закрыт резервной батарейкой с высотой больше, чем радиатор. Особенно мне понравилось потом читать у Adaptec того же «ну, это его нормальная рабочая температура. Не волнуйтесь». Ответственно заявляю: при такой «нормальной рабочей температуре» контроллер безбожно и непредсказуемо-предсказуемо глючил;

  2. Одному отечественному сборщику серверов. «Берём толстый жгут проводов. Скрепляем его, чтобы он был толстым, плотным, надёжным. Вешаем это прямо перед забором воздуха вентиляторами продува серверного корпуса. Идеально!». На «полу» сервера было дофига места, длины кабелей тоже хватало, но сделали почему-то так.

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

Но полный функционал реализован далеко не всегда. В частности, мне понадобились температуры жёстких дисков с нового RAID-контроллера (ну люблю я температуры, что поделать 🙂 ), которых в оригинальном темплейте не было. Пришлось самому реализовывать температуры и заодно autodiscover физических дисков: https://github.com/automatize-it/zabbix-lsi-raid/commit/1d3a8b3a0e289b8c2df637028475177a2b940689

Можно видеть, какой HDD и даже SSD стоит перед отсеком с БП сервера и хуже охлаждается
Можно видеть, какой HDD и даже SSD стоит перед отсеком с БП сервера и хуже охлаждается

Оригинальный репозиторий, вероятно, заброшен, как это довольно часто бывает.

Хотелка № 5, на десерт: спецжелезка 2

Алгоритм действий и примеры кода:

вызываем phantomjs с кукой и сценарием:

phantomjs.exe --cookies-file=cookie.txt C:\cmd\yota_signal\scenery.js
//получаем общий уровень сигнала
var url = "http://192.168.2.1/html/home.html";
var page = require('webpage').create();
page.open(url, function(status) {
  //console.log("Status: " + status);
  if(status === "success") {
	
	var sgnl = page.evaluate(function() {
		return document.getElementById("status_img").innerHTML; //
	});
	
	var stt = page.evaluate(function() {
		return document.getElementById("index_connection_status").innerText; //
	});
	
	var sttlclzd = "dis";
	var sgnlfnd = "NA";
	
	if (stt.indexOf("Подключено") != -1) {sttlclzd = "conn";}
		
	if (sgnl.indexOf("icon_signal_01") != -1) {sgnlfnd = "1";}
	else {
		var tmpndx = sgnl.indexOf("icon_signal_0");
		sgnlfnd = sgnl.substring(tmpndx+13,tmpndx+14);
	}
	
	console.log(sttlclzd+","+sgnlfnd);
	
	var fs = require('fs');
		
		try {
			fs.write("C:\\cmd\\siglvl.txt", sgnlfnd, 'w');
		} catch(e) {
			console.log(e);
		}
    
  }
  phantom.exit();
});
//получаем технические параметры сигнала через какбэ предназначенный для этого "API"
var url = "http://192.168.2.1/api/device/signal"; 
var page = require('webpage').create();

  
	page.onLoadFinished = function() {
		
		//console.log("page load finished");
		//page.render('export.png');
		console.log(page.content);
		
		parser = new DOMParser();
		xmlDoc = parser.parseFromString(page.content,"text/xml");

		var rsrq = xmlDoc.getElementsByTagName("rsrq")[0].childNodes[0].nodeValue.replace("dB","");
		var rsrp = xmlDoc.getElementsByTagName("rsrp")[0].childNodes[0].nodeValue.replace("dBm","");
		var rssi = xmlDoc.getElementsByTagName("rssi")[0].childNodes[0].nodeValue.replace("dBm","").replace(">=","");
		var sinr = xmlDoc.getElementsByTagName("sinr")[0].childNodes[0].nodeValue.replace("dB","");
		
		var fs = require('fs');
		
		try {
			fs.write("C:\\cmd\\rsrq.txt", rsrq, 'w');
			fs.write("C:\\cmd\\rsrp.txt", rsrp, 'w');
			fs.write("C:\\cmd\\rssi.txt", rssi, 'w');
			fs.write("C:\\cmd\\sinr.txt", sinr, 'w');
		} catch(e) {
			console.log(e);
		}
		
		phantom.exit();
	};
	
	page.open(url, function() {
		page.evaluate(function() {
		});
    });

Конструкция запускается из планировщика задач. В Zabbix-агенте производится лишь чтение соответствующих файлов:

UserParameter=internet.devices.huawei1.signal.level,type C:\cmd\siglvl.txt 
Особое внимание на SINR. Он должен быть 10+. Ну, иногда и правда был. Около 4-5 утра обычно
Особое внимание на SINR. Он должен быть 10+. Ну, иногда и правда был. Около 4-5 утра обычно

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

Итого

Стоит ли заморачиваться на Zabbix, если у вас 20 машин и 1-2 сервера, да ещё и инфраструктура Windows?

Как можно понять из вышеизложенного, работы будет много. Я даже рискну предположить, что объёмы работ и уровень квалификации для них сравнимы с решением «свелосипедить своё с нуля по-быстрому на коленке».

Не стоит рассматривать Zabbix как панацею или серебряную пулю.

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

А красивые графики дают усладу глазам и часто — новое видение процессов в динамике.

Если захочется внедрить, то могу пообещать, как минимум — скучно не будет! 😉

Оцените статью
Хостинги