Создание скриптов проверки состояния системы и оповещений
Собирайте показатели нагрузки, памяти и диска и запускайте оповещения при достижении порогов из скриптов по расписанию
«Создание скриптов проверки состояния системы и оповещений» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- Автоматизация создания пользователей и групп
- Управление службами systemd и создание файлов модулей
- Автоматизация дисков, файловых систем и монтирования
- Создание скриптов проверки состояния системы и оповещений