Вопрос: Предупреждение о сценарии bash при ошибке


У меня есть сценарий. ls, cp, mv Я хочу, чтобы если какая-либо из команд завершилась ошибкой, это должно быть предупреждено по электронной почте, а также после успешного конкурса. Есть идеи? Я могу настроить оповещение по электронной почте, но хочу знать, как проверить ошибки и успешную попытку.


4
2018-03-27 18:45


Источник


Похоже, вы хотите отслеживать доступ к вашему серверу. Это не лучший способ установить ограничения или вести журнал. Альтернатива для ls было бы find -maxdepth 1 -ls, mv / cp может быть заменен скриптом python / perl или комбинацией с tar, Конечно, можно разместить свои собственные двоичные файлы в системе и выполнить их. Что бы вы хотели сделать? - Lekensteyn


Ответы:


Вы можете продолжить выполнение серии команд до «сбой», используя «&&» для последовательного запуска команд; каждая команда возвращает «true», вызывая выполнение следующей команды. Затем используйте «||» для запуска команды при сбое, например:

#!/bin/bash

cp foo bar \
  && mv bar bar{,.bak} \
  && echo "good so far" \
  && ls file123 | tee -a /tmp/msg.txt \
  && mailx -u user -s "success" -f /tmp/msg.txt \
  ||  mailx -u user -s "failure" -f ~/err.txt

Поскольку это может стать беспорядочным, используйте функции, такие как

#!/bin/bash

do_work() {
  mv... || return 1
  cp... || return 1
  return 0
}

report() {
  [ "$1" = "ok" ] && mailx ....
  [ "$1" != "ok" ] && mailx -s "$1" ....
  return 0
}

do_work \
  && report ok 
  || report err

Далее, продолжая из вышеприведенного примера, вы можете добавлять общие правила через «ловушку» в скрипте, который всегда будет выполнять определенные команды, если какой-либо тип состояния ошибки будет возвращен в любой точке сценария (включая получение элемента управления-c (прерывание ) во время выполнения скрипта):

#!/bin/bash
tmp=/tmp/msg.$$.txt

# Cleanup: delete tmp files on exit. On any error, trap and exit... then cleanup
trap 'echo "cleaning up tmpfiles..." && rm $tmp >/dev/null 2>&1' 0
trap "exit 2" 1 2 3 15

...

do_work && exit 0

(Disclaimer ... команды, показанные выше, являются общим псевдокодом и просто напечатаны из памяти, не запуская их. Typos, безусловно, существует.)


4
2018-05-04 22:55



Ницца. Мне нравится, насколько чистый этот ответ. Станьте мертвым простым, переходите к немного более чистому способу сделать это. - jorfus


У Bash нет встроенных предупреждений об этом, вам нужно записать его в свой скрипт, проверив $? переменная (содержит код выхода последней команды запуска) и принимает на нее действие.

Мертвая простая проверка того, что электронные письма будут выглядеть так:

if [ $? -ne 0 ]
then
    <send me email however you want to about failure>
else
    <send me email about success how ever you want> 
fi

Обязательно проверьте свою командную документацию, чтобы убедиться, что успешное выполнение устанавливает код выхода 0.


6
2018-03-27 18:51



с опозданием, fwiw, bash имеет встроенную функцию «выхода на любую ошибку» (set -e, то же, что и другой ответ, используя shabang #!/bin/bash -e), на каком событии (trap) вы можете выполнить определенное действие, например, отправить электронное письмо. Но это не всегда будет работать так, как вы ожидаете, поэтому обычно требуется более ручное управление условиями, как описано в этом ответе (проверка состояния выхода через $?, || и / или &&). mywiki.wooledge.org/BashFAQ/105 - michael


Вы используете оболочку команды mailwrap, которая принимает некоторые параметры, определяющие, кому отправлять почту, перед запуском команды, которая является ее параметром. Команда mailwrap отправляет только сообщения электронной почты, если есть выход, или если сценарий завершился неудачно. Есть много вариантов, и они хорошие упражнения, чтобы писать сами, если вам не нравятся те, которые вы найдете.

На #! линии самого скрипта, вы используете -e, так что любой конвейер команд, который не работает, заставляет сценарий прерываться в этой точке. Вы также можете использовать -u, чтобы прервать использование неиспользуемой переменной.

Чтобы выполнить команду сбоя не отмените сценарий, добавьте || true, читать как «или true», так что сбой не имеет значения. (Более идиоматично, || : что то же самое).

Если вы хотите точно увидеть, когда команда с нормально-молчанием вышла из строя, вы используете команду mailwrap, которая не отправляет электронную почту просто из-за вывода на stderr, а затем вы используете -v на оболочке #! line, чтобы трассировать команды по мере их запуска.


3
2018-03-27 20:29





Или передайте вывод скрипта в почту независимо от результата, пока вы не будете счастливы, что он работает.

Что-то вроде:

(cat $resultofscript) | mailx -s "Subject" me@me.com


1
2018-03-27 19:26