Сценарий Bash соответствует выводу grep и отправляет сообщение

Я разрабатываю сценарий для 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
2
задан 8 July 2014 в 16:00
1 ответ

В выдержках, которые вы разместили, на самом деле есть ряд проблем. Одна из них заключается в том, что раздел "Команды в переменных" не делает того, что вы думаете. В частности, что делает 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
6
ответ дан 3 December 2019 в 09:17

Теги

Похожие вопросы