Была поставлена задача: реализовать мониторинг БД Oracle средствами Zabbix, а именно — отслеживать параметры табличных пространств на определенном инстансе. Раз задача поставлена, значит делаем. Как известно, Zabbix предоставляет возможность через предопределенный тип данных осуществлять запросы к базам данным и получать результат запроса. На официальном сайте разработчиков Zabbix есть очень хорошая документация по настройке ODBC-мониторинга.
У нас сервер Zabbix 3.0.4 под управлением Centos 7. Ранее ODBC мониторинг не был настроен, а следовательно, нужно открывать инструкции и начинать установку и настройку.
Согласно инструкции с официального сайта Zabbix был установлен пакет unixODBC. Так как UnixODBC-драйвер для Oracle триальный, а бюджет под эту задачу не выделяли, было принято решение — искать другой способ. Перелопатив кучу сайтов с инструкциями установки клиента Oracle, были скачаны с сайта oracle.com пакеты:
oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
oracle-instantclient11.2-sqlplus-11.2.0.3.0-1.x86_64.rpm
oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm
oracle-instantclient11.2-odbc-11.2.0.3.0-1.x86_64.rpm
После того, как все эти пакеты были установлены, осталось только произвести настройки клиента и unixODBC. В результате все настройки были произведены и осталось только протестировать, что все работает.
Перелогиниваемся под пользователем zabbix и выполняем команду isql, согласно инструкции.
[user@serverZabbix]$ isql -v CMSAHI username/password
Все ок. Пробуем получить тот же результат из веб Zabbix. После настройки элемента данных «Мониторинг БД» ждем результата. Но не тут-то было. Элемент данных перешел в статус «Не поддерживается». Получаем ошибку: Cannot connect to ODBC DSN:[SQL_ERROR]:[01000][0][[unixODBC][Driver Manager]Can't open lib '/usr/lib/oracle/11.2/client64/lib/libsqora.so.11.1': file not found]|.
Странная ошибка, тем более, что указанный файл по указанному пути есть.
Начался процесс поиска причины и попытки исправить ошибку. После нескольких дней поиска, перепробовав кучу советов, найденных в интернете, набрёл на тикет в баг-трекере Zabbix. По описанию проблемы – это как раз наша проблема. Что же делать? Тикет открыт, баг найден и в последующих версиях Zabbix, а следовательно, если причина нашей ошибки именно этот баг, настроить мониторинг не получится. Ну не ставить же свежевышедшую версию Zabbix ради решения одной задачи.
В голову пришла мысль: а что, если для подключения к БД использовать не unixODBC а SqlPlus, который был установлен вместе с пакетом oracle-instantclient11.2-sqlplus-11.2.0.3.0-1.x86_64.rpm. Исходя из этой идеи, необходимо настроить клиент oracle для подключения.
Клиент Oracle был установлен в /usr/lib/oracle/11.2/client64. Первое, что нужно сделать – это создать файл tnsnames.ora и заполнить его данными для подключения к БД oracle. Для этого нужно создать папку для хранения этого файла:
sudo mkdir /usr/lib/oracle/11.2/client64/network/admin –p
В созданной директории нужно создать файл с именем tnsnames.ora и заполнить его. Обязательно нужно проверить, чтобы у всех созданных директорий и самого файла были права доступа на чтение для пользователя zabbix.
Далее, нужно создать скрипт для подключения к БД и выполнения запросов. Ниже пример скрипта для выполнения простых селектов:
#!/bin/sh
## Для корректной работы нужно задать переменные окружения ниже
export ORACLE_HOME=/usr/lib/oracle/11.2/client64
export PATH=$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib64:/usr/lib:$ORACLE_HOME/bin
export TNS_ADMIN=$ORACLE_HOME/network/admin
## Директория для хранения sql – файлов. Созданная предварительно.
## Обязательно убедиться, что пользователю zabbix выданы права доступа на запись и чтение
scriptLocation=/etc/zabbix/SqlScripts
## Тут задается абсолютный путь и название создаваемого файла с выполняемым запросом
## в качестве первого параметра скрипта предполагается передавать какую-то уникальную ## строку, для идентификации файла с запросом
sqlFile=$scriptLocation/sqlScript_"$1".sql
## Записываем выполняемый запрос в файл
echo "$2" > sqlFile;
## Собственно, ниже подключаемся к БД и выполняем запрос из ранее сохраненного файла.
## Логин и пароль открытые, не хорошо.
username="$3"
password="$4"
tnsname="$5"
var=$($ORACLE_HOME/bin/sqlplus -s $username/$password@$tnsname < $sqlFile)
## Получаем результат запроса из полученной выше строки и возвращаем результат.
echo $var | cut -f3 -d " "
Скрипт необходимо поместить в папку /etc/zabbix/externalscripts – папка для хранения скриптов внешних проверок (см настройки zabbix_server.conf строка ExternalScripts=/etc/zabbix/externalscripts). Также скрипту необходимо выдать права доступа на чтение и выполнение пользователю zabbix. Скрипт готов. Настраиваем элемент данных «Внешняя проверка» в веб-интерфейсе Zabbix как на скрине ниже.
Созданный ранее скрипт принимает сл. параметры:
- Идентификатор файла с запросом (строка)
- Простой запрос (строка)
- логин для подключения к БД (строка)
- Пароль, для подключения к БД (строка)
- TNS БД, к которой хотим подключиться (строка)
На скрине выше поле «Ключ» заполнено следующим образом:
getOracleSelect.sh["TestSelect","select count(*) from testTable;","username","password","CMSAHI"]
где «TestSelect» – строковый идентификатор, для формирования sql-файла;
«select count(*) from testTable;» – сам запрос.
«username» и «password» – данные подключения к базе
«tnsname» – название базы (см tnsnames.ora)
! ВАЖНО! Запрос должен возвращать значение только одной колонки результирующей таблицы, если ожидается получить численное или текстовое значение результата выборки.
После того, как элемент создан, если все настроено верно, веб-интерфейс Zabbix отобразит результат выполнения запроса.
Данный метод, конечно же, имеет ряд недостатков, но, в качестве временного решения он работает. Таким недостатком, например, является то, что большой и сложный запрос вписывать в качестве параметра очень неудобно.
Для получения параметров занятого табличного пространства использован скрипт ниже:
SELECT round((totalspace — freespace) * 100 / decode(maxspace, 0, totalspace, maxspace), 2) "%USED"
FROM (SELECT tablespace_name, SUM (bytes) / (1024*1024*1024) totalspace, Sum(maxbytes)/ 1024/1024/1024 maxspace
FROM dba_data_files
GROUP BY tablespace_name) a,
(SELECT tablespace_name, SUM (Bytes) / (1024*1024*1024) freespace
FROM dba_free_space
GROUP BY tablespace_name) b
WHERE A.TABLESPACE_NAME = B.TABLESPACE_NAME (+)
AND A.TABLESPACE_NAME = 'TAB_SPACE1';
Так как требуется мониторить всего несколько табличных пространств, под каждое был создан свой sql-файл. Для решения поставленной задачи, скрипт был изменен. Ниже сам скрипт:
#!/bin/sh
export ORACLE_HOME=/usr/lib/oracle/11.2/client64
export PATH=$PATH:$ORACLE_HOME/bin
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib64:/usr/lib:$ORACLE_HOME/bin
export TNS_ADMIN=$ORACLE_HOME/network/admin
scriptLocation=/etc/zabbix/SqlScripts
sqlFile=$scriptLocation/getPUsedTableSpace_"$1".sql
username="$2"
password="$3"
tnsname="$4"
var=$($ORACLE_HOME/bin/sqlplus -s $username/$password@$tnsname < $sqlFile)
echo $var | cut -f3 -d " "
Ключ для элемента данных, соответственно, выглядит так:
getOracleSelect.sh["TAB_SPACE1","username","password","CMSAHI"]
где 'TAB_SPACE1' — наименование табличного пространства.
Как видно из скрина выше, веб-интерфейс Zabbix получает результаты выполнения запроса и отображает процентное значение использованного табличного пространства.
Остается только настроить триггеры и действия оповещений.
Если кому-то поможет данный способ, буду рад. Если у кого-то будут идеи по модернизации скриптов и самого подхода, минуя unixODBC, пишите.
Автор: AT Consulting