LINUX.ORG.RU

Статистика postfix на bash для zabbix

 , , ,


0

1

Всем привет! Знаю, в интернете есть как минимум два готовых скрипта с описанием для мониторинга postfiх, но пишу свой, чтобы разобраться в вещах, с которыми еще не сталкивался ранее.

Первый вариант логики скрипта был таков: собираем стату по cron с помощью Pflogsumm раз в 5 и 10 минут, результат записываем в два разных файла. Далее скрипт на баше прочесывает результаты двух файлов (с результатами от pflogsumm), сверяет разницу между значениями, делает вычисления, получившиеся результаты пишет в файлики, которые читает заббикс-агент. Все работает, пишет, но проблема - каждые 10 минут я получаю 0 по всем параметрам, это связано с тем, что результат за 5 и 10 минут совпал по выводу.

Решил переписать, и сразу немного облагородить текст скрипта. Хотел уйти от постоянной сверки старых и новых значений, но не могу. В 00 происходит смена суток, в это время pflogsumm пересоберет статистику, уже за новый день. Проблема получается, если в 23:55 у меня было значение 50 rejected, а в 00:00 значение rejected = 1, и тогда я получу 49 reject'ов в 00:00, что неправильно.

Первая версия скрипта:

## BYTES RECEIVED
TEMP_RECEIVED=$(/bin/grep "bytes received" /tmp/postfix/temp5 | awk '{print $1}')
DATY_RECEIVED=$(/bin/grep "bytes received" /tmp/postfix/temp10 | awk '{print $1}')
DELTA1_RECEIVED=$(($TEMP_RECEIVED - $DATY_RECEIVED))
DELTA2_RECEIVED=$(($DATY_RECEIVED - $TEMP_RECEIVED))
if [ "$TEMP_RECEIVED" -eq "$DATY_RECEIVED" ]
then
        echo "0" > /tmp/postfix/postfix.bytes.received
else
        if (($TEMP_RECEIVED > $DATY_RECEIVED))
        then
                echo $DELTA1_RECEIVED > /tmp/postfix/postfix.bytes.received
        else
                echo $DELTA2_RECEIVED > /tmp/postfix/postfix.bytes.received
        fi
fi

И так для каждого параметра, который мониторится.

Новая версия предполагает:

##Old data of Received
BYTES_R=$(< /tmp/postfix/postfix.bytes.received)

##Get new values
ResPF=$(/usr/sbin/pflogsumm -h 0 -u 0 -d today --bounce_detail=0 --deferral_detail=0 --reject_detail=0 --smtpd_warning_detail=0 --no_no_msg_size /var/log/mail.log)
## Transmitt new values in variables
BYTES_RN=$(/bin/grep "bytes received" $ResPF | awk '{print $1}')

##Сравниваем старые и новые значения
if [ "$BYTES_RN -ne $BYTES_R" ]
then
        echo $((BYTES_RN - BYTES_R)) | tr -d \- > /tmp/postfix/postfix.bytes.received
else
        echo "0" > /tmp/postfix/postfix.bytes.received
fi

Пример неправильного вывода из скрипта - когда старое значение = 50, новое значение в 00:00 = 1, в графике заббикса я получу 49, а должен 1. Как элегантно обсчитать это вот все безобразие, которое у меня навелосипедилось?

TEMP_RECEIVED=$(/bin/grep «bytes received» /tmp/postfix/temp5 | awk '{print $1}')

Я бы промолчал, если б у вас не появилось что-то новенькое. Хрен с ним, что эта классика давно обсосана насчёт идиотизма grep|awk, когда правильно просто:

awk '/bytes received/  {print $1}' /tmp/postfix/temp5
но почему у вас /bin/grep, но просто awk ?

Если по делу, то ваши TEMP_RECEIVED могут быть пустыми и потому нельзя сравнивать как -eq, хотя можно, но предварительно проверить на пусто и установить в 0:

TEMP_RECEIVED=${TEMP_RECEIVED:-0}
Что-то у вас со временными файлами явно перебор. Надо пересилить себя и научиться обходиться без них.

vodz ★★★★★
()
Ответ на: комментарий от vodz

полностью справедливые замечания!

Работе с bash, sed, awk, и прочим-прочим системным утилитам я учусь, и применяю те средства, которые мне оказались знакомы. В идеале я и хочу написать то, что будет работать без всяких лишних вызовов, это будет после достижения базовой функциональности.

но почему у вас /bin/grep, но просто awk ?

Где-то ранее столкнулся с тем, что grep не был обнаружен, дописал /bin/grep и все заработало. awk же был добавлен позже, видимо, в тот момент времени, ему уже не нужен был полный путь.

Надо пересилить себя и научиться обходиться без них.

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

Aborigen1020
() автор топика
Ответ на: комментарий от Aborigen1020

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

Мониторинг же у вас будет в цикле, потому не надо запоминать старое значение во временном файле. Впрочем, если хотите, по получению сигналов SIGTERM/SIGINT/etc можно и записывать. Это будет хороший пилотаж.

ResPF у вас лишняя переменная, правильнее как-то так:

#!/bin/bash

##Old data of Received
BYTES_R=
read BYTES_R 2> /dev/null < /tmp/postfix/postfix.bytes.received
BYTES_R=${BYTES_R:-0}

# включаем запоминание во временный файл при сигнале
trap 'echo $BYTES_R > /tmp/postfix/postfix.bytes.received; exit 1' SIGHUP SIGINT SIGQUIT SIGTERM

while true; do
 ##Get new values 
 BYTES_RN=$(/usr/sbin/pflogsumm -h 0 -u 0 -d today --bounce_detail=0 --deferral_detail=0 --reject_detail=0 --smtpd_warning_detail=0 --no_no_msg_size /var/log/mail.log | awk 'BEGIN {sum=0} /bytes received/  {sum+=$1} END {print sum}')
 ##получаем abs(разницы)
 BYTES_R=$((BYTES_RN - BYTES_R < 0 ? BYTES_R - BYTES_RN : BYTES_RN - BYTES_R)) 
 # что-то делаем ещё
 ......
done

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 2)
Ответ на: комментарий от vodz

ResPF у вас лишняя переменная

Возможно, что нет, так как наблюдаемых параметров несколько, всего 7.

Разве не проще получить весь вывод, а потом его разбирать на кусочки, чем вызывать полный вывод 7 раз с последующим разбором?

Aborigen1020
() автор топика
Ответ на: комментарий от Aborigen1020

Разве не проще получить весь вывод, а потом его разбирать на кусочки, чем вызывать полный вывод 7 раз с последующим разбором?

Да, но это нечестный приёмчик. Вы привели скрипт без намёка, что оно вам вообще нужно. Но и тут переменная не нужна. Если вывод как param=value, то вот как-то так:

        while read l; do
                tag=${l%%=*}
                val=${l#*=}
                case "${tag^^}" in
                 param1) param1=$val;;
                 param2) param2=$val;;
                esac
        done << EOF
$(/usr/sbin/pflogsumm ..... /var/log/mail.log)
EOF

vodz ★★★★★
()
Ответ на: комментарий от vodz

Спасибо, буду разбирать ваш пример. Надеюсь я пойму синтаксис и смогу его применить осознанно

Aborigen1020
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.