Архив метки: zabbix

В чем опасность использовать прямую работу с БД если есть API

Жил был скрипт, который использовал вот таакой запрос к БД Zabbix:

select sendto from media where userid in (select userid from (select users_groups.userid from operations inner join opmessage_grp on opmessage_grp.operationid=operations.operationid inner join users_groups on opmessage_grp.usrgrpid=users_groups.usrgrpid where operations.actionid in (select actionid from conditions where conditiontype=2 and value=%s union all select actionid from conditions where conditiontype=0 and value in (SELECT groups.groupid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE triggers.triggerid=%s) union all select actionid from conditions where conditiontype=1 and value in (SELECT hosts.hostid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE triggers.triggerid=%s)) union all select opmessage_usr.userid from operations inner join opmessage_usr on opmessage_usr.operationid=operations.operationid where operations.actionid in (select actionid from conditions where conditiontype=2 and value in (select triggers.triggerid from triggers where triggers.triggerid = %s union all select triggers.templateid from triggers where triggers.triggerid = %s) union all select actionid from conditions where conditiontype=0 and value in (SELECT groups.groupid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE triggers.triggerid=%s) union all select actionid from conditions where conditiontype=1 and value in (SELECT hosts.hostid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE triggers.triggerid=%s))) as us group by userid union all select userid from users_groups where usrgrpid=18) and mediatypeid=5

Единственной функцией котого было дать список телефонов пользователей по id триггера. И работал бы этот скрипт еще долго, если бы не случилось обновление Zabbix с 3.4 до 4.4 Структура БД изменилась. Запрос работать перестал. Посмотрел я на него, посмотрел.. И понял, я наверное был не в себе когда его писал, и повторить такой подвиг больше не смогу. Решил переписать его использую API Zabbix. Вышло много понятнее 😉

echo "-получаем api-key\n";
$res=$zab->Auth($login, $password);

$triggerid=$options["t"];
$txt=$options["s"];
$users_id_for_sms=array();
echo "-действия по триггеру\n";
$res=$zab->Execute("action.get", ["triggerids"=>$triggerid,"output"=>'extend','selectOperations'=>'extend','selectRecoveryOperations'=>'extend','selectFilter'=>'extend']);
ParseRes($res);
echo "-получаем хост\n";
$hosts=$zab->Execute("host.get", ["triggerids"=>$triggerid]);
foreach ($hosts->result as $host) {
    $hostid=$host->hostid;
    $hostname=$host->name;
    echo "--действия по хосту $hostid $hostname\n";
    $res=$zab->Execute("action.get", ["hostids"=>$hostid,"output"=>'extend','selectOperations'=>'extend','selectRecoveryOperations'=>'extend','selectFilter'=>'extend']);
    ParseRes($res);
    $hostsg=$zab->Execute("hostgroup.get", ["hostids"=>$hostid]);
    foreach ($hostsg->result as $hostg) {
        $groupid=$hostg->groupid;
        echo "--- действия по группе хоста $groupid\n";   
        $res=$zab->Execute("action.get", ["groupids"=>$groupid,"output"=>'extend','selectOperations'=>'extend','selectRecoveryOperations'=>'extend','selectFilter'=>'extend']);
        ParseRes($res);

    }    
};
echo "- пользователи ZABBIX\n";   
var_dump($users_id_for_sms); 
$sms=array();
foreach ($users_id_for_sms as $userid) {    
    $res=$zab->Execute("user.get", ["userids"=>$userid,"output"=>'extend','status'=>0,"selectMedias"=>"extend"]);                     
    foreach ($res->result as $usersinfo) {        
        foreach ($usersinfo->medias as $md) {
            if ($md->mediatypeid==5){
              $sms[]=$md->sendto;  
            };
        };
        
    }
}
var_dump($sms);

function ParseRes($res){
global $zab,$users_id_for_sms;
    if (count($res->result)!=0){
        foreach ($res->result as $oper) {
            foreach ($oper->operations as $vl) {
                echo "---получаю пользователей группы\n";
                foreach ($vl->opmessage_grp as $usergroups) {
                  $usrgrpid= $usergroups->usrgrpid;
                  echo "----$usrgrpid\n";
                  $res=$zab->Execute("user.get", ["usrgrpids"=>$usrgrpid,"output"=>'extend','status'=>0]);                  
                  foreach ($res->result as $user) {
                   $users_id_for_sms[]=$user->userid;
                  };                                                      
//                  $res=$zab->Execute("user.get", ["usrgrpids"=>15,"output"=>'extend','status'=>0]);                  
//                  foreach ($res->result as $user) {
//                   $users_id_for_sms[]=$user->userid;
//                  };                                                                        
                };
                echo "---добавляю просто пользователей\n";                
                 //var_dump($vl->opmessage_usr);
                foreach ($vl->opmessage_usr as $userslist) {
                   $users_id_for_sms[]= $userslist->userid;
                };
                
            };            
        }
    };                             
};

Работа с API Zabbix из PHP

Поискал, поискал, ничего толкового не нашел. Пришлось написать самому. Выложил на GitHub. Описание актуального API Zabbix тут.

Пример использования:

include_once 'zabbix.php';

$url="https://my_zabbix.ru/api_jsonrpc1.php";
$login="weoriufeowiuf";
$password="owerierfoiewroi";

@include_once 'config.php';

// инициализация класса true/false - вывод в режиме debug
$zab=new Tzabbix(false);
$zab->SetCurlOpt(CURLOPT_URL,$url);
echo "-получаем api-key\n";
$res=$zab->Auth($login, $password);
if (isset($res->result)==true){
    if ($res->result!==false){        
        $res=$zab->Execute("host.get", ["output"=>["hostid","host"],"selectInterfaces"=>["interfaceid","ip"]]);
        var_dump($res);
    } else {
        var_dump($res);        
        die(-1);
    };    
} else {
  echo "--не понятная ошибка. попробуйте переключить в debug=true";  
};

Вывод списка неподдерживаемых элементов данных Zabbix скриптом

Задачу можно решить скриптом на python:

#!/usr/local/bin/python
# coding=utf-8

import socket
import re
from pyzabbix import ZabbixAPI
import time
import requests
requests.packages.urllib3.disable_warnings()

zapi = ZabbixAPI("https://укауц.укаукацук.ru")
zapi.session.verify = False
zapi.login("укацука", "уцкацукацука")


hosts = zapi.host.get();
for hs in hosts:        
    triggers = zapi.item.get(hostids=[hs["hostid"]],);
    for tr in triggers:
        if tr["state"]=="1" and tr["status"]=="0":         
         print hs["hostid"],"|",hs["host"],"|",tr["itemid"].encode('utf8'),"|",tr["name"].encode('utf8');

Контроль касс Атол в Zabbix

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

Пример скрипта:

#!/usr/bin/python3.5
# -*- coding: utf-8 -*-
import base64
import ctypes
import sys
import json
import datetime
import os
import platform
from pprint import pprint

from lib import IFptr
#fptr = IFptr("")

#get extr param
if len(sys.argv)==1:
    print ("Возможные параметры:")
    print ("--info IP - общая информация о ККМ")
    exit(0)
arg=sys.argv[1]
if arg=="--info":
    ip=sys.argv[2];
    
LIBRARY_PATH = os.path.dirname(os.path.abspath(__file__))
fptr = IFptr(os.path.join(LIBRARY_PATH, "libfptr10.so"))
#connect to ATOL
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_MODEL, str(IFptr.LIBFPTR_MODEL_ATOL_AUTO))
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_PORT, str(IFptr.LIBFPTR_PORT_TCPIP))
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_IPADDRESS, ip)
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_IPPORT,"5555")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_ACCESS_PASSWORD,"0")
fptr.setSingleSetting(IFptr.LIBFPTR_SETTING_USER_PASSWORD,"30")

fptr.applySingleSettings()
#открываем соединение
fptr.open()
isOpened = fptr.isOpened()
if isOpened==0:
    print ("9) Доступность:",0)
    exit(1)
    
if arg=="--info":
    fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_REG_INFO)
    fptr.fnQueryData()

    taxationTypes               = fptr.getParamInt(1062)
    agentSign                   = fptr.getParamInt(1057)
    ffdVersion                  = fptr.getParamInt(1209)
    print("Версия ФН:",ffdVersion)

    autoModeSign                = fptr.getParamBool(1001)
    offlineModeSign             = fptr.getParamBool(1002)
    encryptionSign              = fptr.getParamBool(1056)
    internetSign                = fptr.getParamBool(1108)
    serviceSign                 = fptr.getParamBool(1109)
    bsoSign                     = fptr.getParamBool(1110)
    lotterySign                 = fptr.getParamBool(1126)
    gamblingSign                = fptr.getParamBool(1193)
    exciseSign                  = fptr.getParamBool(1207)
    machineInstallationSign     = fptr.getParamBool(1221)
    fnsUrl                      = fptr.getParamString(1060)
    organizationVATIN           = fptr.getParamString(1018)
    organizationName            = fptr.getParamString(1048)
    organizationEmail           = fptr.getParamString(1117)
    paymentsAddress             = fptr.getParamString(1187)
    registrationNumber          = fptr.getParamString(1037)
    machineNumber               = fptr.getParamString(1036)
    ofdVATIN                    = fptr.getParamString(1017)
    ofdName                     = fptr.getParamString(1046)
    print("1) Организация:",organizationName)
    print("2) ОФД:",ofdName)
        
    fptr.setParam(IFptr.LIBFPTR_PARAM_DATA_TYPE, IFptr.LIBFPTR_DT_STATUS)
    fptr.queryData()
    serialNumber    = fptr.getParamString(IFptr.LIBFPTR_PARAM_SERIAL_NUMBER)
    modelName       = fptr.getParamString(IFptr.LIBFPTR_PARAM_MODEL_NAME)
    firmwareVersion = fptr.getParamString(IFptr.LIBFPTR_PARAM_UNIT_VERSION)
    print("3) S/N:",serialNumber)
    print("4) Модель:",modelName)
    print("5) Прошивка:",firmwareVersion)
    fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_VALIDITY)
    fptr.fnQueryData()
    dateTime            = fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
    print("6) Дата окончания ФН:",dateTime)
    fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_LAST_RECEIPT)
    fptr.fnQueryData()
    documentNumber      = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
    print("7) Номер чека:",documentNumber)
    # Получение информации о неотправленных документах
    fptr.setParam(IFptr.LIBFPTR_PARAM_FN_DATA_TYPE, IFptr.LIBFPTR_FNDT_OFD_EXCHANGE_STATUS)
    res=fptr.fnQueryData()
    unsentCount = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENTS_COUNT)
    if unsentCount>0:
        unsentFirstNumber = fptr.getParamInt(IFptr.LIBFPTR_PARAM_DOCUMENT_NUMBER)
        unsentDateTime = fptr.getParamDateTime(IFptr.LIBFPTR_PARAM_DATE_TIME)
        print ("8) Не фискализировано:",unsentCount)
        fptr.close()    
        del fptr
        exit(1)
    else:
        print ("8) Не фискализировано:",0)
    print ("9) Доступность:",1)

Пример выполнения:

root@pavel-All-Series:~/online_kassa# ./common.py --info 192.168.0.103
Версия ФН: 105
1) Организация: Индивидуальный предприниматель Пупкин Александр Владимирович
2) ОФД: ООО "Компания "Тензор"
3) S/N: 00103452021133752352
4) Модель: АТОЛ 55Ф
5) Прошивка: 1245
6) Дата окончания ФН: 2021-06-07 00:00:00
7) Номер чека: 414
8) Не фискализировано: 0
9) Доступность: 1

Пример оформления триггера в агенте zabbix:

UserParameter=ping_kassa,/home/pavel/online_kassa/common.py --info 192.168.0.103 | grep "9)" | awk '{print $3}'

UserParameter=non_fiskalize,/home/pavel/online_kassa/common.py --info 192.168.0.103 | grep "8)" | awk '{print $3}'

Еще один полезный SQL запрос для Zabbix

Получение триггеров с учетом зависимостей. Т.е. Если некий тригер А зависит от триггера Б, то его в списке не будет.

SELECT (UNIX_TIMESTAMP()-triggers.lastchange)/60 as minut,hosts.host,        triggers.description,        triggers.comments,        triggers.triggerid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE hosts.status = 0   AND items.status = 0   AND triggers.status = 0   AND triggers.priority=5   AND triggers.value=1 and ((UNIX_TIMESTAMP()-triggers.lastchange)/60)>15 and triggers.triggerid in (select triggerid_up from trigger_depends where triggerid_down in (SELECT triggers.triggerid FROM triggers INNER JOIN functions ON triggers.triggerid=functions.triggerid INNER JOIN items ON items.itemid=functions.itemid INNER JOIN hosts ON hosts.hostid=items.hostid INNER JOIN hosts_groups ON hosts_groups.hostid=hosts.hostid INNER JOIN groups ON groups.groupid=hosts_groups.groupid WHERE hosts.status = 0   AND items.status = 0   AND triggers.status = 0   AND triggers.priority=5   AND triggers.value=1 and ((UNIX_TIMESTAMP()-triggers.lastchange)/60)>15 group by triggerid))  group by triggers.triggerid