Как временно остановить выполнение только определенной части задания в crontab?

Вопрос или проблема

У меня установлена 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-задачи позволяет вам более гибко работать с событиями и их отчетностью без необходимости приостанавливать выполнение всего скрипта. Используя временные файлы, вы сможете легко отслеживать, когда и какие уведомления были отправлены, не нарушая общий процесс выполнения задачи.

Оцените материал
Добавить комментарий

Капча загружается...