Я разрабатываю сценарий для monit состояния, проверяющего, таким образом, я могу отправить хорошо сообщения о состоянии на сервер NagiOS NSCA (пассивные проверки). Проблема, которую я имею, состоит в том, что мой сценарий удара все еще отправляет сообщения, если бы сценарии 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)
Команда состояния Monit
# 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=$(команда)
, так это выполняет команду немедленно, а затем помещает свой вывод в переменную. Так как команда 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=$(монитор 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 фатальных проблемы (и одна маленькая загвоздка): во-первых, это сравнение строки строки "статус" с "не запущен" и "недоступен", но Вы хотите сравнить вывод команды статуса монитора | grep ...
. Это просто исправить, используя "$monstat"
вместо "статус"
.
Во-вторых, часть & &
означает, что это сработает только если оба совпадения , то есть, если что-то не работает и что-то недоступно. Я бы ожидал, что вы захотите вызвать отчет, если либо что-то не работает , либо что-то недоступно, поэтому вместо этого используйте ||
.
В-третьих, вы делаете тест на равенство строк, то есть проверяете, не состоит ли весь отчет из "не работает", и ничего больше . Я уверен, что вы хотите посмотреть, содержит ли он "не запущен" или "недоступен". Вы можете сделать это с помощью более продвинутого условного выражения ([[ ]]
вместо [ ]
), которое позволяет использовать подстановочные знаки:
if [[ "$monstat" = *"not running"* ]] || [[ "$monstat" = *"not accessible"* ]]; then
... где подстановочные знаки (*
) совпадают с тем, что находится до и после рассматриваемой строки. BTW, обратите внимание, что я также использовал =
вместо ==
-- на самом деле это более стандартно в shell скриптах. Другой вариант - использовать grep
для сравнения:
if echo "$monstat" | grep -E -q "not running|not accessible"; then
обратите внимание, что здесь нет [ ]
или [[ ]]
; оператор if
смотрит, удалась команда или нет, и grep
удается только в том случае, если она находит совпадение. Часть -q
говорит grep
не печатать какое бы то ни было найденное совпадение - мы не хотим видеть совпадение, просто чтобы знать, было ли оно.
На самом деле, мне приходит в голову, что может быть четвёртая серьёзная проблема: заглавно ли -статус монитора
в сообщениях о его статусе? Это важно, потому что "не работает" (или "не работает") не будет совпадать с "не работает". Если он прописан с большой буквы, то либо выполните поиск с прописными буквами аналогичным образом, либо выполните поиск по регистру с помощью либо [["$monstat" = *[nN]"ot "[rR]"unning "* ]]
-i
опции grep.
О, и последнее замечание: если Вам не нужна опция или
, то просто оставьте ее в стороне. Не нужно иметь пустое с :
псевдо-командой.
В любом случае, со всеми этими изменениями, вот что я получаю для всего сценария:
#!/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
EDIT: Я думаю, что, возможно, я неправильно понял смысл теста; он должен посылать данные, если все в порядке? Я предполагал, что он посылает данные об ошибке, и, следовательно, должен посылать данные только в том случае, если есть проблема. Если это так, используйте соответствующие !
для инвертирования смысла совпадений. В версии [[ ]]
используйте !=
, чтобы посмотреть, найдена ли строка , а не :
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