В 2018 году я написал шаблон для Zabbix 3.4:
Мониторинг postfix через zabbix
Теперь я переделал шаблон мониторинга Postfix под пятый Zabbix. Мониторится статистика отправленных писем: Bounced, Deferred, Expired, Queue, Refused, Reject, Sent. Соединения Connect From и Connect To.
9 элементов данных, 5 триггеров, три графика.
Пока переделывал, нашёл ошибку и сразу создал вторую версию шаблона. Внёс изменение в скрипт postfix_data.sh. Оказалось, что при большом количестве писем возможна ситуация, когда значения во временном файле postfix_data.dat дублируются после перезагрузки сервера. Сделал сортировку с удалением дублей. Также считываю только уникальное значение, чтобы уменьшить вероятность считывания неверных данных.
Установка шаблона
Скачать шаблон для Zabbix 5.0: zabbix_postfix
Импортируем шаблон zbx5_postfix.xml. Подключаем шаблон к хостам.
В макросах шаблона можно отредактировать параметры:
- {$POSTFIX_MAX_BOUNCED} — 1000. Граница срабатывания триггера Bounced.
- {$POSTFIX_MAX_DEFERRED} — 20000. Граница срабатывания триггера Deferred.
- {$POSTFIX_MAX_QUEUE} — 30000. Граница срабатывания триггера Queue.
- {$POSTFIX_MAX_REFUSED} — 1000. Граница срабатывания триггера Refused.
- {$POSTFIX_MAX_REJECTED} — 1000. Граница срабатывания триггера Reject.
В зависимости от нагрузки на сервер, вы можете сами установить границы срабатывания триггеров.
На серверах, которые собираемся мониторить, установим пакет logtail:
apt-get install logtail -y
Копируем папку со скриптами в /etc/zabbix/scripts/. В ней у нас:
- /etc/zabbix/scripts/postfix_data.sh
#!/bin/bash
MAILLOG=/var/log/mail.log
TEMPDIR=/tmp/postfix_data/
PARTLOG=${TEMPDIR}partlog.log
OFFSETFILE=${TEMPDIR}offset.dat
DATAFILE=${TEMPDIR}data.dat
LOGTAIL=/usr/sbin/logtail
VALS=( 'bounced' 'deferred' 'sent' 'expired' 'reject' 'connect_from' 'connect_to' 'refused' 'queue' )
[ ! -e "${TEMPDIR}" ] && mkdir "${TEMPDIR}" && chown zabbix:zabbix "${TEMPDIR}"
[ ! -e "${DATAFILE}" ] && touch "${DATAFILE}" && chown zabbix:zabbix "${DATAFILE}"
[ ! -e "${PARTLOG}" ] && touch "${PARTLOG}" && chown zabbix:zabbix "${PARTLOG}"
# read data
if [ -n "$1" ]; then
key=$(echo ${VALS[@]} | grep -wo $1)
if [ -n "${key}" ]; then
value=$(cat "${DATAFILE}" | sort -u | grep -e "^${key};" | cut -d ";" -f2)
echo "${value}"
else
exit 2
fi
# write data
else
"${LOGTAIL}" -f"${MAILLOG}" -o"${OFFSETFILE}" > ${PARTLOG}
for i in "${VALS[@]}"; do
case ${i} in
"bounced")
value=$(grep "status=bounced" ${PARTLOG} | wc -l)
;;
"deferred")
value=$(grep "status=deferred" ${PARTLOG} | wc -l)
;;
"sent")
value=$(grep "status=sent" ${PARTLOG} | wc -l)
;;
"expired")
value=$(grep "status=expired" ${PARTLOG} | wc -l)
;;
"reject")
value=$(grep "NOQUEUE: reject" ${PARTLOG} | wc -l)
;;
"connect_from")
value=$(grep ": connect from" ${PARTLOG} | wc -l)
;;
"connect_to")
value=$(grep ": connect to" ${PARTLOG} | wc -l)
;;
"refused")
value=$(grep "refused to talk to me:" ${PARTLOG} | wc -l)
;;
"queue")
value=$(mailq | grep -v "Mail queue is empty" | grep -c "^[A-F0-9]")
;;
esac
if grep -q ${i} ${DATAFILE}; then
sed -i "s/^${i};.*$/${i};${value}/" "${DATAFILE}"
else
echo "${i};${value}" >> "${DATAFILE}"
sort -u "${DATAFILE}" -o "${DATAFILE}"
fi
done
fi
Не забываем про владельца и права:
chown -R root\: /etc/zabbix/scripts
chmod a+x /etc/zabbix/scripts/*
Добавляем скрипт postfix_data.sh в cron от рута:
crontab -e
*/10 * * * * bash /etc/zabbix/scripts/postfix_data.sh
service cron restart
Копируем userparameter_postfix.conf в папку с пользовательскими переменными, у меня это /etc/zabbix/zabbix_agentd.conf.d/userparameter_postfix.conf.
UserParameter=postfix[*],/etc/zabbix/scripts/postfix_data.sh $1
Не забываем про владельца и права:
chown root\: /etc/zabbix/zabbix_agentd.conf.d/userparameter_postfix.conf
chmod 644 /etc/zabbix/zabbix_agentd.conf.d/userparameter_postfix.conf
Перезапускаем агент:
service zabbix-agent restart
Готово. Раз в 10 минут будет срабатывать скрипт для подсчёта и обновления статистических данных Postfix. Данные хранятся во временном файле.
Примечание: тысячи писем отображаются как "килописьма": Kmails. Это не баг, это фича.
Версии
v2
Начальная версия
v3
Забыл в скрипте назначить правильные права на offset файл. Это не критично, но некрасиво... Добавил строку:
[ ! -e "${OFFSETFILE}" ] && touch "${OFFSETFILE}" && chown zabbix:zabbix "${OFFSETFILE}"
Вручную можно также добавить эту строку и выполнить:
chown zabbix:zabbix /tmp/postfix_data_offset.dat
v4
Благодаря Rene Oberlaender в комментариях к статье выяснилось, что в Ubuntu 20 или выше наблюдается проблема. Пользователь root не может обновить временный файл, принадлежащий пользователю zabbix в каталоге /tmp. Всему виной systemd. По новым правилам по умолчанию нельзя редактировать чужие файлы в каталоге с атрибутом липкого бита "sticky bit".
Что делать?
Вариант 1
Модифицировать скрипт таким образом, чтобы он не сохранял временные файлы в папке /tmp, хранить данные в другом месте.
Вероятно сработает вариант, при котором можно создать папку в каталоге /tmp, а уже в ней хранить временные файлы. Именно этот вариант применён в четвёртой версии.
Вариант 2
Редактировать /usr/lib/sysctl.d/protect-links.conf. Изменить параметр:
fs.protected_regular=2
на
fs.protected_regular=0