0Pricing
DevOps Bootcamp · Урок

Создание скриптов проверки состояния системы и оповещений

Собирайте показатели нагрузки, памяти и диска и запускайте оповещения при достижении порогов из скриптов по расписанию

«Создание скриптов проверки состояния системы и оповещений» — бесплатный урок DevOps Bootcamp на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения DevOps Bootcamp, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс DevOps Bootcamp содержит 4 уроков всего.

Почему важны проверки состояния системы

Рабочие серверы могут незаметно терять производительность. Скачки нагрузки CPU, утечки памяти и заполненные диски приводят к сбоям — но только если никто не замечает проблему вовремя. Сценарии проверки состояния системы автоматизируют цикл мониторинга: собирают показатели, сравнивают их с порогами и отправляют оповещения до того, как пользователи столкнутся с последствиями.

  • Запускаемые через cron, они выполняются каждые несколько минут без участия человека
  • Они создают единообразный вывод с отметками времени, подходящий для объединения журналов
  • Логика на основе порогов делает оповещения полезными — не каждый кратковременный сбой вызывает уведомление дежурной команды

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

Получение средней нагрузки

Linux предоставляет средние значения нагрузки за 1, 5 и 15 минут через /proc/loadavg и команду uptime. Для сценариев /proc/loadavg — самый удобный источник: он не зависит от локали и различий в разборе данных между дистрибутивами.

Приведённый ниже фрагмент считывает среднюю нагрузку за 1 минуту и сохраняет её в переменной для сравнения с порогом. cut извлекает первое поле, а awk удаляет десятичную часть для целочисленного сравнения, используя bc для арифметики с плавающей точкой.

#!/usr/bin/env bash
# Read 1-minute load average from /proc/loadavg
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
echo "Raw load average: $LOAD_RAW"

# Number of CPU cores — used to normalise load
CPU_CORES=$(nproc)
echo "CPU cores: $CPU_CORES"

# Compute load percentage (load / cores * 100) using bc
LOAD_PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)
echo "Load %: $LOAD_PCT"

Сравнение с порогом для чисел с плавающей точкой

Bash не умеет напрямую сравнивать числа с плавающей точкой — [ 1.5 -gt 1.2 ] выдаёт ошибку. Есть два стандартных решения:

  • bc — выводит 1 (истина) или 0 (ложь) для выражения сравнения
  • awk — может вычислять условия для чисел с плавающей точкой внутри конвейера

Использование bc делает логику понятной и удобной для тестирования. Шаблон $(echo "$A > $B" | bc) возвращает 1, когда условие выполняется; это проверяется с помощью [ ... -eq 1 ].

#!/usr/bin/env bash
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
CPU_CORES=$(nproc)
THRESHOLD=80  # alert when load % exceeds 80%

LOAD_PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)

# bc returns 1 if the expression is true
if [ "$(echo "$LOAD_PCT > $THRESHOLD" | bc)" -eq 1 ]; then
    echo "ALERT: Load is ${LOAD_PCT}% (threshold ${THRESHOLD}%)"
else
    echo "OK: Load is ${LOAD_PCT}%"
fi

Сбор показателей памяти

/proc/meminfo — достоверный источник статистики памяти в Linux. Основные поля:

  • MemTotal — общий объём физической RAM в кБ
  • MemAvailable — приблизительный объём памяти в кБ, доступный для новых выделений без обращения к подкачке (более показателен, чем MemFree)

Самый удобный способ извлечь эти значения — использовать awk с сопоставлением по шаблону. Деление MemAvailable на MemTotal с последующим вычитанием из 100 даёт процент использования памяти, на основе которого срабатывает порог оповещения.

#!/usr/bin/env bash
# Extract memory figures from /proc/meminfo (values in kB)
MEM_TOTAL=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)
MEM_AVAIL=$(awk '/^MemAvailable:/ {print $2}' /proc/meminfo)

# Used memory percentage
MEM_USED_PCT=$(echo "scale=2; (1 - $MEM_AVAIL / $MEM_TOTAL) * 100" | bc)

echo "Total RAM : ${MEM_TOTAL} kB"
echo "Available : ${MEM_AVAIL} kB"
echo "Used      : ${MEM_USED_PCT}%"

Сбор показателей использования диска

Команда df показывает использование файловых систем. Для сценариев особенно важны два флага:

  • -h — понятные человеку размеры (только для отображения; не используйте их в арифметике)
  • --output=pcent,target — столбцы в формате, удобном для разбора программами (GNU coreutils)

Перебор всех смонтированных файловых систем позволяет сценарию обнаружить любой критически заполненный раздел, а не только /. Знак % удаляется с помощью tr -d '%' перед целочисленным сравнением.

#!/usr/bin/env bash
DISK_THRESHOLD=85

# Skip header line with tail -n +2
# --output=pcent,target gives "85% /var" style lines
df --output=pcent,target | tail -n +2 | while read -r USED_PCT MOUNT; do
    # Remove the % sign for arithmetic
    USED_INT=${USED_PCT//%/}

    if [ "$USED_INT" -ge "$DISK_THRESHOLD" ]; then
        echo "ALERT: Disk $MOUNT is ${USED_PCT} full"
    else
        echo "OK   : Disk $MOUNT is ${USED_PCT} full"
    fi
done

Структурированный вывод оповещений с отметками времени

Сообщения оповещений без отметок времени почти бесполезны в файлах журналов или отчётах по электронной почте. Единообразный префикс значительно упрощает разбор журналов с помощью grep или агентов отправки журналов.

Определите в начале сценария небольшую функцию оповещения. Она добавляет в начало отметку времени ISO-8601, уровень важности и название проверки. Все оповещения записываются одновременно в stdout и файл журнала через tee.

  • date -u +"%Y-%m-%dT%H:%M:%SZ" — отметка времени UTC, не зависящая от локали
  • Запись в stderr для ALERT и в stdout для OK отделяет важные сообщения от лишних в конвейерах
#!/usr/bin/env bash
LOG_FILE="/var/log/healthcheck.log"

alert() {
    local LEVEL="$1"   # OK | WARN | ALERT
    local CHECK="$2"
    local MSG="$3"
    local TS
    TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    local LINE="[$TS] [$LEVEL] [$CHECK] $MSG"

    if [ "$LEVEL" = "ALERT" ]; then
        echo "$LINE" | tee -a "$LOG_FILE" >&2
    else
        echo "$LINE" | tee -a "$LOG_FILE"
    fi
}

# Usage examples
alert "OK"    "DISK"  "/ is 42% full"
alert "ALERT" "DISK"  "/var is 91% full"

Отправка оповещений по электронной почте с помощью mail и sendmail

Самый простой механизм оповещений на сервере — электронная почта через локальный MTA (postfix, sendmail или msmtp). Команда mail (из mailutils или bsd-mailx) создаёт и отправляет сообщение одной строкой.

  • -s — тема сообщения
  • Передавайте текст сообщения через stdin
  • На серверах без локального MTA замените mail вызовом curl для обращения к API сервиса транзакционной электронной почты

Защитите отправку блокировкой для устранения дубликатов, чтобы одно слишком частое условие не переполнило почтовый ящик.

#!/usr/bin/env bash
ALERT_EMAIL="ops@example.com"
LOCK_DIR="/tmp/healthcheck_locks"
mkdir -p "$LOCK_DIR"

send_alert() {
    local CHECK="$1"
    local MSG="$2"
    local LOCK="$LOCK_DIR/${CHECK}.lock"

    # Only send if no lock exists (prevents repeated emails within the hour)
    if [ ! -f "$LOCK" ]; then
        echo "$MSG" | mail -s "[ALERT] $CHECK on $(hostname)" "$ALERT_EMAIL"
        touch "$LOCK"
        # Lock expires after 1 hour via cron or find+delete
        echo "Alert sent for $CHECK"
    else
        echo "Alert suppressed for $CHECK (lock active)"
    fi
}

send_alert "HIGH_LOAD" "Load average exceeded 80% on $(hostname) at $(date)"

Составление полного скрипта проверки состояния

Теперь объедините все три проверки — загрузки, памяти и диска — в один цельный скрипт с настраиваемыми порогами в начале. Именно такой шаблон используется в промышленной автоматизации системного администрирования:

  • Константы объявлены в начале, чтобы их можно было легко настраивать без изменения логики
  • Каждая проверка вынесена в отдельную функцию для удобства чтения и модульного тестирования
  • Функция main координирует вызовы
  • Код завершения 1, если сработало хотя бы одно оповещение, и 0 в противном случае — это позволяет подключать скрипт к платформам мониторинга, таким как Nagios и Icinga
#!/usr/bin/env bash
set -euo pipefail

# ── Thresholds ───────────────────────────────────────────
LOAD_THRESHOLD=80   # percent of CPU capacity
MEM_THRESHOLD=90    # percent used
DISK_THRESHOLD=85   # percent used
ALERT_EMAIL="ops@example.com"
LOG_FILE="/var/log/healthcheck.log"
ALERT_FIRED=0

# ── Helpers ──────────────────────────────────────────────
ts()    { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
log()   { echo "[$(ts)] $*" | tee -a "$LOG_FILE"; }
alert() { log "ALERT: $*"; echo "$*" | mail -s "[ALERT] $(hostname)" "$ALERT_EMAIL" 2>/dev/null; ALERT_FIRED=1; }

# ── Checks ───────────────────────────────────────────────
check_load() {
    local raw cores pct
    raw=$(cut -d' ' -f1 /proc/loadavg)
    cores=$(nproc)
    pct=$(echo "scale=2; $raw / $cores * 100" | bc)
    if [ "$(echo "$pct > $LOAD_THRESHOLD" | bc)" -eq 1 ]; then
        alert "Load ${pct}% exceeds ${LOAD_THRESHOLD}%"
    else
        log "OK load=${pct}%"
    fi
}

check_memory() {
    local total avail pct
    total=$(awk '/^MemTotal:/    {print $2}' /proc/meminfo)
    avail=$(awk '/^MemAvailable:/{print $2}' /proc/meminfo)
    pct=$(echo "scale=2; (1 - $avail / $total) * 100" | bc)
    if [ "$(echo "$pct > $MEM_THRESHOLD" | bc)" -eq 1 ]; then
        alert "Memory ${pct}% used (threshold ${MEM_THRESHOLD}%)"
    else
        log "OK memory=${pct}%"
    fi
}

check_disk() {
    df --output=pcent,target | tail -n +2 | while read -r used mnt; do
        local pct_int=${used//%/}
        if [ "$pct_int" -ge "$DISK_THRESHOLD" ]; then
            alert "Disk $mnt at ${used}"
        else
            log "OK disk $mnt=${used}"
        fi
    done
}

main() {
    log "=== Health check START ==="
    check_load
    check_memory
    check_disk
    log "=== Health check END (alerts=$ALERT_FIRED) ==="
    exit "$ALERT_FIRED"
}

main

Планирование с помощью Cron

Скрипт проверки состояния полезен только тогда, когда запускается автоматически. cron — стандартный планировщик Unix. Отредактируйте общесистемную таблицу заданий cron или отдельный файл в /etc/cron.d/, чтобы запланировать запуск скрипта.

  • Запуск каждые 5 минут: */5 * * * *
  • Всегда используйте абсолютные пути в cron — переменная $PATH в окружении cron содержит минимальный набор путей
  • Перенаправляйте вывод, чтобы cron не отправлял электронное письмо после каждого запуска: >> /var/log/healthcheck.log 2>&1
  • Добавьте MAILTO="" в начало таблицы заданий, чтобы отключить собственные письма cron
# /etc/cron.d/healthcheck
# Run the health check every 5 minutes as root
MAILTO=""
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

*/5 * * * * root /usr/local/sbin/healthcheck.sh >> /var/log/healthcheck.log 2>&1

Предотвращение лавины оповещений с помощью блокировок задержки

Если порог непрерывно превышен, простой скрипт отправляет оповещение каждые 5 минут — инженер успевает получить десятки писем, прежде чем сможет отреагировать. Блокировка задержки повторных оповещений подавляет повторные оповещения в течение настраиваемого периода.

Шаблон выглядит так: при первом оповещении создаётся файл блокировки; последующие оповещения пропускаются, пока файл не станет старше заданного периода подавления; find с параметром -mmin атомарно проверяет возраст файла, не требуя вычислений с датами.

#!/usr/bin/env bash
LOCK_DIR="/tmp/hc_locks"
COOLDOWN_MIN=60  # suppress repeat alerts for 60 minutes
mkdir -p "$LOCK_DIR"

should_alert() {
    local check="$1"
    local lock="$LOCK_DIR/${check}.lock"

    if [ ! -f "$lock" ]; then
        # No lock — allow alert and create lock
        touch "$lock"
        return 0  # true: send alert
    fi

    # Lock exists — check if it is older than the cooldown
    # find returns the filename only if it's OLDER than COOLDOWN_MIN
    local expired
    expired=$(find "$lock" -mmin +"$COOLDOWN_MIN" 2>/dev/null)

    if [ -n "$expired" ]; then
        touch "$lock"  # refresh lock timestamp
        return 0       # cooldown expired — allow alert
    fi

    return 1  # still within cooldown — suppress
}

# Usage
if should_alert "HIGH_LOAD"; then
    echo "Sending load alert..."
    # mail -s "..." ops@example.com <<< "Load too high"
else
    echo "Load alert suppressed (cooldown active)"
fi

Тестирование и проверка скрипта контроля состояния

Перед развёртыванием проверьте скрипт тремя способами:

  • Проверка синтаксиса: bash -n healthcheck.sh обнаруживает ошибки разбора, не выполняя скрипт
  • Режим трассировки: bash -x healthcheck.sh выводит каждую выполняемую команду — это бесценно при отладке
  • Переопределение порогов: временно снизьте пороги почти до нуля, чтобы скрипт вызвал оповещения на исправном узле и подтвердил работоспособность всего пути оповещения

Для проверки пути отправки электронной почты во время тестирования перенаправьте mail в файл журнала с помощью флага MOCK_MAIL:

#!/usr/bin/env bash
# Smoke-test the alert path without sending real email
MOCK_MAIL=true
ALERT_EMAIL="ops@example.com"

send_mail() {
    local subject="$1"
    local body="$2"
    if [ "$MOCK_MAIL" = true ]; then
        echo "[MOCK MAIL] To: $ALERT_EMAIL | Subject: $subject"
        echo "[MOCK MAIL] Body: $body"
    else
        echo "$body" | mail -s "$subject" "$ALERT_EMAIL"
    fi
}

# Override threshold to guarantee an alert fires
LOAD_THRESHOLD=0   # Any load will exceed 0%
LOAD_RAW=$(cut -d' ' -f1 /proc/loadavg)
CPU_CORES=$(nproc)
PCT=$(echo "scale=2; $LOAD_RAW / $CPU_CORES * 100" | bc)

if [ "$(echo "$PCT > $LOAD_THRESHOLD" | bc)" -eq 1 ]; then
    send_mail "[ALERT] Load on $(hostname)" "Load is ${PCT}%"
fi

Проверка знаний: стратегия задержки повторных оповещений

Рассмотрите следующий сценарий: задание cron для проверки состояния запускается каждые 5 минут. Использование диска в /var превышает 85% и остаётся на этом уровне 3 часа. Вы хотите, чтобы дежурный инженер получал оповещение раз в час, а не каждые 5 минут. Какая стратегия реализации наиболее уместна?

Итоги урока: скрипты проверки состояния системы

На этом уроке вы создали полностью готовый к промышленной эксплуатации конвейер проверки состояния системы и оповещения. Ниже перечислены основные принципы, которые следует применять и дальше:

  • Источник истины: считывайте метрики из /proc/loadavg и /proc/meminfo — они стабильны, не зависят от локали и доступны на каждом узле Linux
  • Арифметика с плавающей точкой: используйте bc для сравнения порогов с плавающей точкой; целочисленное сравнение Bash (-gt) работает только с целыми числами
  • Обход дисков: используйте df --output=pcent,target, чтобы проверять каждую подключённую файловую систему, а не только /
  • Структурированное журналирование: добавляйте к каждой строке временную метку UTC и уровень важности, чтобы журналы было удобно обрабатывать с помощью grep и без лишних преобразований передавать в централизованные системы журналирования
  • Блокировки задержки: файлы блокировки, проверяемые с помощью find -mmin, предотвращают лавину оповещений без изменения расписания cron
  • Композиция: завершайте работу с кодом 1, когда срабатывает любое оповещение, чтобы скрипт интегрировался с Nagios, Icinga и другими платформами мониторинга
  • Тестирование: используйте bash -n для проверки синтаксиса, bash -x для трассировки при отладке и флаг MOCK_MAIL для проверки пути оповещения на исправных узлах

Запланируйте запуск готового скрипта через /etc/cron.d/, и ваша инфраструктура будет непрерывно контролировать себя, отправляя оповещения только при существенном превышении порогов.

Часто задаваемые вопросы

Урок «Создание скриптов проверки состояния системы и оповещений» бесплатный?

Да — полный текст урока «Создание скриптов проверки состояния системы и оповещений» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс DevOps Bootcamp, подпишись на CoddyKit PRO. Курс DevOps Bootcamp содержит 4 уроков всего.

Чему я научусь в уроке «Создание скриптов проверки состояния системы и оповещений»?

Собирайте показатели нагрузки, памяти и диска и запускайте оповещения при достижении порогов из скриптов по расписанию Ты практикуешь DevOps Bootcamp с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать DevOps Bootcamp?

Предыдущий опыт не требуется. DevOps Bootcamp на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Создание скриптов проверки состояния системы и оповещений»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке DevOps Bootcamp?

Да. Каждый урок DevOps Bootcamp включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Автоматизация создания пользователей и групп
  2. Управление службами systemd и создание файлов модулей
  3. Автоматизация дисков, файловых систем и монтирования
  4. Создание скриптов проверки состояния системы и оповещений
← Назад к DevOps Bootcamp