Я разрабатываю сценарий для проверки статуса монитора, чтобы я мог отправлять сообщения о статусе OK на сервер NagiOS NSCA (пассивные проверки). Проблема, с которой я столкнулся, заключается в том, что мой сценарий bash по-прежнему отправляет сообщения, если функция grep сценария не включает ничего, что могло бы вызвать отправку сообщения.
Сценарий:
Переменные
rsysl='rsyslog'
log='messages'
Команды в переменных
host=$(hostname)
monstat=$(monit status|grep -C 1 '$rsysl')
nsca_status=$(echo -e "$host\t$rsysl\t0\tOK" | /usr/sbin/send_nsca -H mon.lv.lan -c /etc/send_nsca.cfg)
Команда мониторинга состояния
# Postfix check
$monstat
Функция отправки сообщения, как вы видите, должна отправлять сообщение только тогда, когда положение дел равно не бегать и не доступный
if [ "status" == "not running" ] && [ "status" == "not accessible" ]; then
$nsca_status
else
:
fi
Вывод grep (в реальной ситуации команда отправки сообщения должна соответствовать Бег и доступный:
# monit status|grep -C 1 'rsyslog'
Process 'rsyslog'
status Running
--
File 'rsyslog-messages-log'
status Accessible
На самом деле в опубликованных вами отрывках есть ряд проблем. Причина, по которой он всегда отправляет сообщения, заключается в том, что раздел «Команды в переменных» не выполняет то, что вы думаете. В частности, что var=$(command)
делает это немедленно выполнить команду, затем поместите его вывод в переменной. Поскольку nsca_status=$( ... | /usr/sbin/send_nsca ... )
команда всегда выполняется, сообщение всегда отправляется - и отправляется до if
заявление, которое должно решить, отправлять его или нет.
В общем, сохранить команду в переменной сложно (см. BashFAQ # 50: Я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу!), и вообще плохая идея. В таком случае либо просто используйте команду напрямую (без попытки сохранить и получить ее), либо используйте функцию:
nsca_status() {
echo -e "$host\t$rsysl\t0\tOK" | /usr/sbin/send_nsca -H mon.lv.lan -c /etc/send_nsca.cfg
}
(а затем выполните его с помощью nsca_status
- нет $
.)
В случае с двумя другими командами в этом разделе вы, вероятно, действительно хотите выполнить их немедленно и сохранить результаты, так что в основном они в порядке. Ну вообще-то проблема с monstat=$(monit status|grep -C 1 '$rsysl')
- одинарные кавычки вокруг $rsysl
предотвратит его расширение как ссылку на переменную, поэтому grep
буду искать $rsysl
, вместо того rsyslog
. Чтобы исправить это, используйте вместо этого двойные кавычки. Ссылки на переменные почти всегда следует заключать в двойные кавычки. Но учтите, что вам следует не затем попробуйте выполнить $monstat
как команду - это попытается выполнить grep
вывод (Process 'rsyslog' status Running ...
) как будто это команда, что не имеет смысла.
Другие проблемы, которые я вижу, находятся в if
заявление:
if [ "status" == "not running" ] && [ "status" == "not accessible" ]; then
... на самом деле здесь 3 фатальных проблемы (и одна небольшая придирка): во-первых, это сравнение строка «статус» с «не запущен» и «недоступен», но вы хотите сравнить вывод monit status | grep ...
команда. Это легко исправить, используйте "$monstat"
вместо того "status"
.
Во-вторых, &&
часть означает, что он сработает, только если обе происходят совпадения; то есть, если что-то не работает и что-то недоступно. Я ожидал, что вы захотите вызвать отчет, если либо что-то не работает или что-то недоступно, поэтому используйте ||
вместо.
В-третьих, вы выполняете проверку на равенство строк; то есть вы проверяете, состоит ли весь отчет из «не запущен» и ничего больше. Я почти уверен, что ты хочешь увидеть, содержит «не работает» или «недоступен». Вы можете сделать это с помощью более продвинутого условного выражения bash ([[ ]]
вместо того [ ]
), что позволяет использовать подстановочные знаки:
if [[ "$monstat" = *"not running"* ]] || [[ "$monstat" = *"not accessible"* ]]; then
... где подстановочные знаки (*
) соответствует тому, что находится до и после рассматриваемой строки. Кстати, обратите внимание, что я также использовал =
вместо того ==
- на самом деле это более стандартно для сценариев оболочки. Другой вариант - использовать grep
для сопоставления:
if echo "$monstat" | grep -E -q "not running|not accessible"; then
обратите внимание, что нет [ ]
или [[ ]]
Вот; в if
оператор смотрит, была ли команда выполнена успешно или нет, и grep
успешно, только если найдет совпадение. В -q
часть говорит grep
не печатать найденное совпадение - мы не хотим видеть совпадение, просто чтобы знать, было ли оно.
На самом деле, мне приходит в голову, что может быть четвертая серьезная проблема: monit status
заглавными буквами его статусные сообщения? Это важно, потому что «Не работает» (или «Не работает») не будет соответствовать «не работает». Если это заглавные буквы, либо используйте заглавные буквы в строке поиска, либо выполните поиск без учета регистра с помощью [[ "$monstat" = *[nN]"ot "[rR]"unning"* ]]
или grep -i
вариант.
О, и последнее замечание: если вам не нужен else
пункт, просто оставьте его. Нет необходимости иметь пустой с :
псевдокоманда.
Во всяком случае, со всеми этими изменениями вот что я получу для всего скрипта:
#!/bin/bash
# Variables
rsysl='rsyslog'
log='messages'
# Function to send a status message
nsca_status() {
echo -e "$host\t$rsysl\t0\tOK" | /usr/sbin/send_nsca -H mon.lv.lan -c /etc/send_nsca.cfg
}
# Store output of commands
host=$(hostname)
monstat=$(monit status|grep -C 1 '$rsysl')
# Send message if there's anything wrong
if [[ "$monstat" = *[nN]"ot "[rR]"unning"* ]] || [[ "$monstat" = *[nN]"ot "[aA]"ccessible"* ]]; then
nsca_status
fi
РЕДАКТИРОВАТЬ: Я думаю, что, возможно, неправильно понял смысл теста; должен ли он отправлять данные, если все в порядке? Я предполагал, что он отправляет статус ошибки и, следовательно, должен отправлять только в случае возникновения проблемы. В этом случае используйте соответствующий !
чтобы перевернуть смысл матчей. в [[ ]]
версия, используйте !=
чтобы увидеть, является ли строка не нашел:
if [[ "$monstat" != *[nN]"ot "[rR]"unning"* ]] && [[ "$monstat" != *[nN]"ot "[aA]"ccessible"* ]]; then
В версии grep одиночный !
переворачивает весь if
тест:
if ! echo "$monstat" | grep -E -i -q "not running|not accessible"; then