Вопрос или проблема
У меня установлена RHEL 8.x / Oracle Linux 8.x с заданием cron, которое выполняется каждые 3 минуты следующим образом. В конце скрипта вы увидите 4 различных if
, которые проверяют различные файлы и отправляют электронные письма в зависимости от статуса.
Допустим, два средних блока if (успех|ОК) сработали и отправили почту, и я хочу, чтобы они сработали снова в задании cron, которое выполнится через 3 минуты, но не отправляли почту. И отправить почту в первом задании cron, которое будет выполняться через 1 час. А затем после отправки почты не отправлять электронные письма снова в течение 60 минут. Таким образом, это будет цикл для каждого блока if.
Если я добавлю sleep 60m, часть после среднего блока if не будет работать в течение 60 минут. Однако я лишь хочу остановить определенный блок if, чтобы он не отправлял почту в течение 60 минут, а остальные продолжали бы работать каждые 3 минуты.
На самом деле, если есть ситуация, когда электронная почта отправляется один раз, я хочу, чтобы она не отправлялась в течение следующих 60 минут и продолжала работу, не затрагивая никакой другой процесс в задании cron. Тот же сценарий будет действителен для неудачных случаев, я просто выбрал два блока if посередине для ясности примера.
Как я могу достичь этого, используя только одно задание cron?
- Содержимое
myJobScript.sh
:... ... ... /usr/local/bin/command -options /dir_1/dir_2/dir_3/....bin > $DIR_NAME/file1_${parameter}_${parameter}.log /usr/local/bin/command -options /dir_1/dir_2/dir_3/....bin > $DIR_NAME/file2_${parameter}_${parameter}.log /usr/local/bin/command -options /dir_1/dir_2/dir_3/....bin > $DIR_NAME/file3_${parameter}_${parameter}.log /usr/local/bin/command -options /dir_1/dir_2/dir_3/....bin > $DIR_NAME/file4_${parameter}_${parameter}.log if grep -E -w 'failure|failed|critical|warning' $DIR_NAME/file1_${parameter}_${parameter}.log >> /dev/null then cat $DIR_NAME/file1_${parameter}_${parameter}.log | mailx -r [email protected] -s "$parameter - что-то" [email protected] fi if grep -E -w 'success|OK' $DIR_NAME/file2_${parameter}_${parameter}.log >> /dev/null then cat $DIR_NAME/file2_${parameter}_${parameter}.log | mailx -r [email protected] -s "$parameter - что-то" [email protected] fi if grep -E -w 'success|OK' $DIR_NAME/file3_${parameter}_${parameter}.log >> /dev/null then cat $DIR_NAME/file3_${parameter}_${parameter}.log | mailx -r [email protected] -s "$parameter - что-то" [email protected] fi if grep -E -w 'failure|failed|critical|warning' $DIR_NAME/file4_${parameter}_${parameter}.log >> /dev/null then cat $DIR_NAME/file4_${parameter}_${parameter}.log | mailx -r [email protected] -s "$parameter - что-то" [email protected] fi
При возникновении ошибок позаботьтесь о том, чтобы задание cron создало именованный файл с временной меткой.
При запуске задания удалите именованный файл, если он старше 1 часа, в противном случае пропустите части задания cron, которые вы не хотите выполнять.
Ответ или решение
Как временно отключить определенные блоки в cron-работе?
Вопрос, касающийся управления блоками кода в вашем crontab задании, может быть решен с использованием файлового подхода. Рассмотрим, как можно настроить ваш скрипт так, чтобы он отправлял письма только раз в час для определенных блоков, сохранив при этом выполнение всех остальных блоков каждые 3 минуты.
1. Подход с использованием временных файлов
Одним из наиболее эффективных способов временно "отключить" определенные блоки скрипта является использование временных файлов с отметками времени. Это позволит регистрировать, когда последний раз был отправлен e-mail, и в зависимости от этого выполнять или пропускать определенные блоки.
2. Пример реализации
Ниже представлен возможный вариант реализации:
#!/bin/bash
# Определите путь к временным файлам
DIR_NAME="/path/to/your/dir"
SUCCESS_MAIL_TIMESTAMP_FILE="$DIR_NAME/success_mail_timestamp"
FAILURE_MAIL_TIMESTAMP_FILE="$DIR_NAME/failure_mail_timestamp"
# Функция для проверки времени
can_send_email() {
local MAIL_TIMESTAMP_FILE=$1
local TIMESTAMP
TIMESTAMP=$(date +%s)
if [[ -f "$MAIL_TIMESTAMP_FILE" ]]; then
local LAST_SENT
LAST_SENT=$(cat "$MAIL_TIMESTAMP_FILE")
# Проверяем, прошло ли больше 3600 секунд (1 час)
if (( TIMESTAMP - LAST_SENT > 3600 )); then
echo 1
return
fi
fi
echo 0
}
# Ваша основная логика
/usr/local/bin/command -options /dir_1/dir_2/dir_3/....bin > $DIR_NAME/file1_${parameter}_${parameter}.log
/usr/local/bin/command -options /dir_1/dir_2/dir_3/....bin > $DIR_NAME/file2_${parameter}_${parameter}.log
/usr/local/bin/command -options /dir_1/dir_2/dir_3/....bin > $DIR_NAME/file3_${parameter}_${parameter}.log
/usr/local/bin/command -options /dir_1/dir_2/dir_3/....bin > $DIR_NAME/file4_${parameter}_${parameter}.log
# Проверка на ошибки
if grep -E -w 'failure|failed|critical|warning' $DIR_NAME/file1_${parameter}_${parameter}.log > /dev/null; then
if [[ $(can_send_email "$FAILURE_MAIL_TIMESTAMP_FILE") -eq 1 ]]; then
cat $DIR_NAME/file1_${parameter}_${parameter}.log | mailx -r [email protected] -s "$parameter - что-то" [email protected]
date +%s > "$FAILURE_MAIL_TIMESTAMP_FILE"
fi
fi
# Проверка на успех
if grep -E -w 'success|OK' $DIR_NAME/file2_${parameter}_${parameter}.log > /dev/null; then
if [[ $(can_send_email "$SUCCESS_MAIL_TIMESTAMP_FILE") -eq 1 ]]; then
cat $DIR_NAME/file2_${parameter}_${parameter}.log | mailx -r [email protected] -s "$parameter - что-то" [email protected]
date +%s > "$SUCCESS_MAIL_TIMESTAMP_FILE"
fi
fi
if grep -E -w 'success|OK' $DIR_NAME/file3_${parameter}_${parameter}.log > /dev/null; then
cat $DIR_NAME/file3_${parameter}_${parameter}.log | mailx -r [email protected] -s "$parameter - что-то" [email protected]
fi
if grep -E -w 'failure|failed|critical|warning' $DIR_NAME/file4_${parameter}_${parameter}.log > /dev/null; then
if [[ $(can_send_email "$FAILURE_MAIL_TIMESTAMP_FILE") -eq 1 ]]; then
cat $DIR_NAME/file4_${parameter}_${parameter}.log | mailx -r [email protected] -s "$parameter - что-то" [email protected]
date +%s > "$FAILURE_MAIL_TIMESTAMP_FILE"
fi
fi
3. Объяснение кода
- Функция
can_send_email
проверяет, прошло ли с момента последней отправки письма больше часа. Если это так, она возвращает 1, что означает, что можно отправлять письмо. - Каждая ветвь условий теперь включает в себя проверку возможности отправки почты с помощью этой функции.
- Временные метки записи о последней отправке сообщений сохраняются в отдельные файлы.
- Благодаря этому другие блоки кода в скрипте продолжают исполняться каждые 3 минуты, не зависимо от статуса получения почты.
Заключение
Данный способ управления отправкой электронных писем в рамках одной cron-задачи позволяет вам более гибко работать с событиями и их отчетностью без необходимости приостанавливать выполнение всего скрипта. Используя временные файлы, вы сможете легко отслеживать, когда и какие уведомления были отправлены, не нарушая общий процесс выполнения задачи.