Требования
Для мониторинга состояния заданий потребуется:
- установить ms sql client для Linux на сервер zabbix (скачать можно с сайта MS, там-же есть инструкция по его установке);
- создать скрипт для внешней проверки;
- создать элемент данных типа внешняя проверка и указать созданный скрипт с параметрами
вот и все, далее указываем требуемую периодичность опроса и получаем данные, можно настроить оповещение.
Пример установки ms sql client
- Скачиваем архив msodbcsql-11.0.2270.0.tar.gz и распаковываем его например в /opt/msodbcsql-11.0.2270.0
- Скачиваем unixODBC нужной версии (wget http://ftp.unixodbc.org/pub/unixODBC/unixODBC-2.3.0.tar.gz) и распаковываем его например в /opt/unixODBC-2.3.0
- Собираем и устанавливаем unixODBC-2.3.0 в отдельное место:
cd /opt/unixODBC-2.3.0 mkdir -p /opt/microsoft/msodbcsql CPPFLAGS="-DSIZEOF_LONG_INT=8" export CPPFLAGS ./configure --enable-gui=no \ --enable-drivers=no \ --enable-iconv \ --with-iconv-char-enc=UTF8 \ --with-iconv-ucode-enc=UTF16LE \ --prefix=/opt/microsoft/msodbcsql \ --libdir=/opt/microsoft/msodbcsql/lib64 \ --sysconfdir=/opt/microsoft/msodbcsql/etc make make install
- Устанавливаем msodbcsql в отдельное место:
cd /opt/msodbcsql-11.0.2270.0 mkdir -p /opt/microsoft/msodbcsql/usr/bin export PATH=/opt/microsoft/msodbcsql/bin:$PATH export LD_LIBRARY_PATH=/opt/microsoft/msodbcsql/lib64 ./install.sh install --bin-dir=/opt/microsoft/msodbcsql/usr/bin \ --lib-dir=/opt/microsoft/msodbcsql/lib64 \ --force
- Создаем пользователя в MS SQL и даем ему права на чтение базы msdb
- Создать скрипт запуска sqlcmd (см. ниже)
Скрипт запуска sqlcmd (mssql_query.sh):
Положить в /etc/zabbix/externalscripts
#!/bin/bash pid=$$ export PATH=/opt/microsoft/msodbcsql/bin:$PATH export LD_LIBRARY_PATH=/opt/microsoft/msodbcsql/lib64 debug=0 USERPW=${1%@*} SERVERDB=${1#*@} SERVER=${SERVERDB%/*} DB=${SERVERDB#*/} PW=${USERPW#*\%} USER=${USERPW%\%*} err="ERROR" QUERY="SET NOCOUNT ON; $2" SQLCMD=/opt/microsoft/msodbcsql/bin/sqlcmd-11.0.2270.0 LOG=/var/log/zabbix/sqlcmd.log test $debug -eq 1 && echo -e "\n$1 $2" | awk '{print "'"$(date)"', '$pid': "$0}'>>$LOG var=$((($SQLCMD -S "$SERVER" -d "$DB" -U "$USER" -P "$PW" -Q "$QUERY" -h-1 -W -r $3 1>&3 || echo "$err" 1>&3 ) 2>&1 | awk '{ print "'"$(date)"', '$pid': Query: '"$0"' '"$1"' '"$2"'"; print "'"$(date)"', '$pid': "$0 }'>>$LOG) 3>&1) if [ -n "$var" -a "$var" != "NULL" ]; then echo "$var" else echo 0 fi
Пример запроса:
./mssql_query.sh User%Password@ServerName/DBName "SELECT * FROM DBName.TestTable WHERE Status=1 group by Status;"
Если используется нестандартный порт, то указать строку соединения так:
./mssql_query.sh User%Password@ServerName,Port/DBName "SELECT * FROM DBName.TestTable WHERE Status=1 group by Status;"
Кроме того в процессе тестирования выявилось наличие ограничения в длине запроса, у меня получилось около 1000 символов, поэтому слишком длинные запросы не стоит задавать…
Пример создания скрипта внешней проверки (mssql_query_agent.sh):
Положить в /etc/zabbix/externalscripts
#!/bin/bash mssql_query=/etc/zabbix/externalscripts/mssql_query.sh step_count="select MAX(sjs.step_id) as max_step_id from dbo.sysjobsteps sjs inner join dbo.sysjobs sj on sjs.job_id = sj.job_id where sj.name = '$2'" stepid="select sj.start_step_id from dbo.sysjobs sj where sj.name='$2' and sj.enabled=1" query="select MAX(sjh.run_date),MAX(sjh.run_time),sjh.run_duration,sjh.run_status,sjs.step_id from dbo.sysjobhistory sjh inner join dbo.sysjobs sj on sjh.job_id=sj.job_id inner join dbo.sysjobsteps sjs on sj.job_id=sjs.job_id and sjh.step_id=sjs.step_id where sj.name='$2' and sj.enabled=1 and sjh.run_date>=(select MAX(last_run_date) from dbo.sysjobsteps sjs inner join dbo.sysjobs sj on sjs.job_id=sj.job_id where sj.name='$2' and step_id in ($stepid)) and sjh.run_time>=(select MAX(last_run_time) from dbo.sysjobsteps sjs inner join dbo.sysjobs sj on sjs.job_id=sj.job_id where sj.name='$2' and step_id in ($stepid)) group by sjh.run_duration,sjh.run_status,sjs.step_id order by MAX(sjh.run_date),sjs.step_id" errlistquery="SELECT sj.name, sjsr.last_run_date, sjsr.last_run_time, sjsr.last_run_outcome FROM dbo.sysjobservers sjsr inner join dbo.sysjobs sj on sj.job_id = sjsr.job_id inner join dbo.sysjobschedules sjsc on sjsc.job_id = sjsr.job_id where sjsr.last_run_outcome<>1 and sjsr.last_run_outcome<>3 and sj.enabled=1 and sjsr.last_run_date > 0 and sjsc.next_run_date > 0 order by sj.name" MSDB="$1" query_str() { $mssql_query "$MSDB" "$query" } query_errlist() { $mssql_query "$MSDB" "$errlistquery" "-s," | sort -u } query_stepcount() { $mssql_query "$MSDB" "$step_count" } jobhistory(){ case $3 in status) query_str | awk 'BEGIN{status=0;count=0} {if(and(status==0,count==2)) {exit} else {status=$4; count=$5}} END{print status}';; lastdate) date -d "$(query_str | awk 'BEGIN{status=0;count=0;date=0;time=0} {if(or(and(status==0,count==2),status==1)) {exit} else {status=$4; count=$5}; date=$1; time=$2} END{print date" "time}' | sed -r -e 's/([0-9]{0,2})([0-9]{2})([0-9]{2})$/\1:\2:\3/' -e 's/([[:space:]])(:[0-9])/\10\2/')" +%s;; stepcount) query_stepcount;; laststepcount) query_str | awk 'BEGIN{status=0;count=0} {if(and(status==0,count==2)) {exit} else {status=$4; count=$5}} END{print count}';; errlist) query_errlist ;; *) query_str | awk '{print $0}';; esac } jobhistory "$1" "$2" "$3"
Пример запроса:
./mssql_query_agent.sh User%Password@ServerName/msdb TestAgentJob status
Скрипт принимает параметры:
- status (статус выполнения задания, описание статусов можно взять на страничке sp_help_jobhistory на сайте МS, коротко скажу что 1 — это все хорошо),
- lastdate (дата последнего запуска),
- stepcount (всего шагов в задании),
- laststepcount (счетчик шагов, которые были выполнены в последний запуск задания),
- errlist (общий список заданий с ошибками) выводит в виде строки, например:
JobName1,LastStartDate1,LastStartTime1,LastStatus1;JobName2,LastStartDate2,LastStartTime2,LastStatus2;....
Создать новый элемент данных и установить:
Тип: Внешняя проверка
Ключ: mssql_query_agent.sh[«{$MSDB}», «{$QUERY_JOB_NAME}», «status»]
или: mssql_query_agent.sh[«{$MSDB}», «», «errlist»]
- {$MSDB} — макрос прописать для узла сети: User%Password@ServerName/msdb
- {$QUERY_JOB_NAME} — макрос прописать для узла сети: TestAgentJob
- status — показать статус, можно указать другие параметры для запроса см. выше
Тип информации: числовой (целое), а для errlist — текст
Тип данных: десятичный
Единица измерения: для параметра lastdate установить unixtime, а для остальных пусто.
Отображение значения: для status можно настроить преобразование согласно списка значений (см. описание sp_help_jobhistory на сайте МS).
Вот и все, осталось все проверить, настроить триггеры и радоваться ))
Правила обнаружения
Для создания правила, можно модернизировать скрипт (mssql_query_agent_list.sh):
#!/bin/bash mssql_query=/etc/zabbix/externalscripts/mssql_query.sh listquery="SELECT sj.name FROM dbo.sysjobservers sjsr inner join dbo.sysjobs sj on sj.job_id = sjsr.job_id inner join dbo.sysjobschedules sjsc on sjsc.job_id = sjsr.job_id where sj.enabled=1 order by sj.name" MSDB="$1" query_list() { $mssql_query "$MSDB" "$listquery" "-s," | sort -u } jobhistory(){ case $2 in list) query_list | awk '{print $0}';; *) query_list | awk 'BEGIN{ s="{\n\t\"data\": [" } { s=s"\n\t{ \"{#SJNAME}\":\""$0"\" }," } END { sub(/,$/,"",s); print s"\n\t]\n}" }' ;; esac } jobhistory "$1" "$2" "$3"
который будет выыводить список заданий в формате JSON.
Пример:
./mssql_query_agent_list.sh "user%password@server,port/msdb"
{ "data": [ { "{#SJNAME}":"Backup.Subplan_1" }, { "{#SJNAME}":"Job1" }, { "{#SJNAME}":"Job2 Test" }, { "{#SJNAME}":"Test 3 Job" } ] }
Использовать данные в формате JSON для настройки правил обнаружения в zabbix
А дальше, как использовать эти данные в формате JSON для настройки правил обнаружения в zabbix, можно прочесть в https://www.zabbix.com/documentation/2.4/ru/manual/discovery/low_level_discovery