Скрипт мониторинга свободного места на диске: оповещения в Telegram, Slack и Email | AdminWiki

Скрипт мониторинга свободного места на диске: оповещения в Telegram, Slack и Email

24 июля 2026 9 мин. чтения

Зачем нужен автоматический мониторинг дискового пространства

Заполненный до предела диск останавливает сервисы. База данных не может записать транзакцию, веб-сервер перестаёт обрабатывать запросы, логи не пишутся, а система начинает вести себя непредсказуемо. Восстановление после такого инцидента занимает от нескольких минут до часов, а в худшем случае приводит к повреждению данных.

Ручная проверка свободного места через SSH или RDP не решает проблему. Администратор узнаёт о переполнении постфактум, когда пользователи уже жалуются на сбой. Ночью или в выходные инцидент остаётся незамеченным до утра.

Автоматический скрипт с оповещениями меняет ситуацию. Вы получаете уведомление в мессенджер или на почту за 15-30 минут до того, как свободное место закончится полностью. Этого времени достаточно, чтобы очистить логи, расширить раздел или перенести данные. Решение не требует установки Zabbix или Prometheus - только Bash или PowerShell и доступ к API выбранного канала связи.

Если вам нужен более глубокий мониторинг с отслеживанием SMART-атрибутов и температуры накопителей, обратите внимание на руководство по автоматическому мониторингу дисков с интеграцией smartd и Grafana. Для централизованного сбора логов с десятков серверов подойдёт связка rsyslog и Graylog, описанная в отдельной статье.

Принцип работы скрипта и логика оповещений

Скрипт выполняет три действия: получает информацию о свободном месте на целевых разделах, сравнивает её с заданным порогом и отправляет оповещение, если порог превышен. Никаких фоновых демонов - только однократный запуск, который cron или Task Scheduler повторяют по расписанию.

Логика срабатывания строится на простом условии: если свободного места меньше порогового значения - отправить уведомление. Чтобы избежать флуда при пограничных значениях, добавьте файл-флаг. Перед отправкой скрипт проверяет наличие флага. Если флаг есть - уведомление уже отправлено, повтор не нужен. Когда место освобождается выше порога - флаг удаляется, и цикл сбрасывается.

Выбор пороговых значений: проценты или гигабайты?

Процентный порог удобен для разнородных дисков. Правило «оповещать при заполнении на 90%» работает и для системного SSD на 120 ГБ, и для массива данных на 10 ТБ. Минус подхода: на большом томе 10% свободного места - это сотни гигабайт, и оповещение может прийти слишком рано.

Абсолютный порог в гигабайтах точнее для предсказуемого прироста данных. Раздел с логами приложений, который стабильно растёт на 2 ГБ в сутки, логично контролировать по остатку в 10 ГБ. Системный раздел с непредсказуемым потреблением лучше мониторить по процентам. Для баз данных комбинируйте оба подхода: основной порог - процентный, дополнительный - абсолютный, чтобы поймать аномально быстрый рост.

Скрипт мониторинга для Linux на Bash

Приведённый скрипт проверяет все смонтированные разделы, исключая псевдо-файловые системы (tmpfs, devtmpfs). Порог задаётся в процентах. При срабатывании вызывается функция отправки оповещения в выбранный канал.

#!/bin/bash

# Порог срабатывания в процентах (оповещать, если занято больше 90%)
THRESHOLD=90

# Файл-флаг для предотвращения повторных уведомлений
FLAG_FILE="/tmp/disk_alert_flag"

# Функция отправки оповещения - раскомментируйте нужный вариант ниже
send_alert() {
    local disk=$1
    local usage=$2
    local message="Внимание: диск $disk заполнен на $usage%"
    
    # Вызов конкретной функции отправки
    send_telegram "$message"
    # send_slack "$message"
    # send_email "$message"
}

# Основной цикл проверки
df -h | grep '^/dev/' | awk '{print $5 " " $6}' | while read output; do
    usage=$(echo $output | awk '{print $1}' | sed 's/%//')
    partition=$(echo $output | awk '{print $2}')
    
    if [ $usage -ge $THRESHOLD ]; then
        if [ ! -f $FLAG_FILE ]; then
            send_alert "$partition" "$usage"
            touch $FLAG_FILE
        fi
    fi
done

# Сброс флага, если все диски в норме
if [ -f $FLAG_FILE ]; then
    all_ok=true
    df -h | grep '^/dev/' | awk '{print $5}' | sed 's/%//' | while read usage; do
        if [ $usage -ge $THRESHOLD ]; then
            all_ok=false
        fi
    done
    if $all_ok; then
        rm -f $FLAG_FILE
    fi
fi

Команда df -h выводит информацию о дисках в человекочитаемом формате. Фильтр grep '^/dev/' отсеивает виртуальные файловые системы. awk извлекает пятый столбец (процент использования) и шестой (точка монтирования). sed 's/%//' убирает символ процента для числового сравнения.

Интеграция с Telegram

Создайте бота через @BotFather в Telegram и получите токен. Узнайте chat_id: отправьте боту сообщение и выполните запрос https://api.telegram.org/bot<ТОКЕН>/getUpdates. В ответе найдёте поле chat.id.

send_telegram() {
    local message=$1
    local token="ВАШ_ТОКЕН"
    local chat_id="ВАШ_CHAT_ID"
    
    curl -s -X POST "https://api.telegram.org/bot$token/sendMessage" \
        -d chat_id="$chat_id" \
        -d text="$message" \
        -d parse_mode="HTML" \
        > /dev/null 2>&1
}

Функция отправляет POST-запрос к Telegram Bot API. Параметр parse_mode="HTML" позволяет форматировать сообщение тегами <b> и <code>. Для промышленного использования вынесите токен и chat_id в переменные окружения или внешний конфигурационный файл с правами 600.

Интеграция со Slack

В настройках рабочего пространства Slack создайте Incoming Webhook. Вы получите URL вида https://hooks.slack.com/services/T.../B.../xxxx. Сохраните его в переменную.

send_slack() {
    local message=$1
    local webhook_url="https://hooks.slack.com/services/ВАШ_ВЕБХУК"
    
    curl -s -X POST -H 'Content-type: application/json' \
        --data "{\"text\":\"$message\"}" \
        "$webhook_url" \
        > /dev/null 2>&1
}

Slack принимает JSON. Для цветового выделения критических оповещений добавьте поле "color": "danger" в секцию attachments. Это визуально отделит аварийные уведомления от обычных сообщений в канале.

Интеграция с Email

Утилита mailx отправляет письма через локальный или внешний SMTP-сервер. Установите пакет: apt install mailutils (Debian/Ubuntu) или yum install mailx (RHEL/CentOS). Настройте SMTP в /etc/mail.rc или используйте локальный Postfix как релей.

send_email() {
    local message=$1
    local recipient="admin@example.com"
    local subject="Критическое заполнение диска"
    
    echo "$message" | mailx -s "$subject" "$recipient"
}

Для отправки через внешний SMTP-сервер (например, Яндекс или Google) добавьте в /etc/mail.rc строки аутентификации. При использовании Gmail потребуется пароль приложения, а не основной пароль аккаунта.

Скрипт мониторинга для Windows на PowerShell

PowerShell получает данные о дисках через Get-CimInstance - этот командлет работает быстрее устаревшего Get-WmiObject и поддерживается во всех актуальных версиях Windows Server и Windows 10/11.

# Порог срабатывания в процентах
$threshold = 90
$flagFile = "C:\Temp\disk_alert_flag.txt"

function Send-Alert {
    param($disk, $usage)
    $message = "Внимание: диск $disk заполнен на $usage%"
    
    # Вызов нужной функции
    Send-Telegram -message $message
    # Send-Slack -message $message
    # Send-Email -message $message
}

$disks = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DriveType -eq 3 }

$alertTriggered = $false

foreach ($disk in $disks) {
    $usage = [math]::Round((($disk.Size - $disk.FreeSpace) / $disk.Size) * 100)
    
    if ($usage -ge $threshold) {
        if (-not (Test-Path $flagFile)) {
            Send-Alert -disk $disk.DeviceID -usage $usage
            New-Item -Path $flagFile -ItemType File -Force | Out-Null
        }
        $alertTriggered = $true
    }
}

# Сброс флага, если все диски в норме
if (-not $alertTriggered -and (Test-Path $flagFile)) {
    Remove-Item -Path $flagFile -Force
}

Фильтр DriveType -eq 3 выбирает только локальные фиксированные диски, исключая сетевые и сменные накопители. Формула расчёта процента использования: (Size - FreeSpace) / Size * 100. Округление до целого числа через [math]::Round() делает вывод читаемым.

Отправка оповещений в Telegram и Slack из PowerShell

Командлет Invoke-RestMethod выполняет HTTP-запросы к API мессенджеров. Для Telegram передайте токен и chat_id в URL, сообщение - в теле запроса.

function Send-Telegram {
    param($message)
    $token = "ВАШ_ТОКЕН"
    $chatId = "ВАШ_CHAT_ID"
    $uri = "https://api.telegram.org/bot$token/sendMessage"
    $body = @{ chat_id = $chatId; text = $message; parse_mode = "HTML" }
    
    try {
        Invoke-RestMethod -Uri $uri -Method Post -Body $body -ErrorAction Stop | Out-Null
    } catch {
        Write-Warning "Ошибка отправки в Telegram: $_"
    }
}

Для Slack формируется JSON с полем text. Блок try/catch перехватывает сетевые ошибки - скрипт не упадёт, если сервер Slack временно недоступен.

function Send-Slack {
    param($message)
    $webhookUrl = "https://hooks.slack.com/services/ВАШ_ВЕБХУК"
    $body = @{ text = $message } | ConvertTo-Json
    
    try {
        Invoke-RestMethod -Uri $webhookUrl -Method Post -Body $body -ContentType "application/json" -ErrorAction Stop | Out-Null
    } catch {
        Write-Warning "Ошибка отправки в Slack: $_"
    }
}

Отправка Email через PowerShell

Командлет Send-MailMessage встроен в PowerShell, но официально помечен как устаревший. Microsoft рекомендует переходить на библиотеку MailKit. Для быстрого решения без внешних зависимостей Send-MailMessage работает в актуальных версиях Windows.

function Send-Email {
    param($message)
    $params = @{
        From       = "server@example.com"
        To         = "admin@example.com"
        Subject    = "Критическое заполнение диска"
        Body       = $message
        SmtpServer = "smtp.example.com"
        Port       = 587
        Credential = New-Object System.Management.Automation.PSCredential("user", (ConvertTo-SecureString "password" -AsPlainText -Force))
        UseSsl     = $true
    }
    
    try {
        Send-MailMessage @params -ErrorAction Stop
    } catch {
        Write-Warning "Ошибка отправки Email: $_"
    }
}

Хранение пароля в открытом виде в скрипте небезопасно. В production-среде сохраните учётные данные в зашифрованном файле через Export-Clixml или используйте Windows Credential Manager. Для серверов, где скрипт запускается от имени SYSTEM, настройте анонимную relay-отправку на внутренний SMTP-сервер.

Автоматизация запуска по расписанию

Скрипт без расписания бесполезен. Настройте периодический запуск, чтобы проверка выполнялась автоматически каждые 15-30 минут. Более частый запуск создаёт избыточную нагрузку, более редкий - увеличивает риск пропустить критическое заполнение.

Настройка cron в Linux

Откройте редактор cron: crontab -e. Добавьте строку запуска. Пример для проверки каждые 30 минут:

*/30 * * * * /usr/local/bin/disk_monitor.sh >> /var/log/disk_monitor.log 2>&1

Перенаправление вывода >> /var/log/disk_monitor.log 2>&1 сохраняет stdout и stderr в лог-файл. Это критически важно для отладки: если скрипт молча перестал работать, вы увидите ошибку в логе. Проверьте, что скрипт имеет права на выполнение: chmod +x /usr/local/bin/disk_monitor.sh.

Для запуска от root используйте sudo crontab -e. Если скрипт должен выполняться от имени обычного пользователя, убедитесь, что у него есть доступ на чтение информации о дисках (команда df работает без повышенных привилегий).

Настройка Task Scheduler в Windows

Откройте «Планировщик заданий» и создайте новую задачу. На вкладке «Общие» установите флажок «Выполнять с наивысшими правами». На вкладке «Триггеры» создайте триггер «По расписанию» с повторением каждые 30 минут и бесконечной длительностью.

На вкладке «Действия» укажите:

  • Действие: «Запуск программы»
  • Программа: powershell.exe
  • Аргументы: -ExecutionPolicy Bypass -File "C:\Scripts\disk_monitor.ps1"

Параметр -ExecutionPolicy Bypass разрешает выполнение неподписанных скриптов. На вкладке «Условия» снимите флажок «Запускать только при питании от сети», если сервер - ноутбук. Для стационарных серверов этот параметр не имеет значения.

Типовые ошибки и их решение

Неверный токен или chat_id Telegram. Симптом: сообщение не приходит, в логах curl ошибка 401 или 400. Диагностика: выполните вручную curl "https://api.telegram.org/bot<ТОКЕН>/getMe". Если возвращается ok: false - токен недействителен. Для проверки chat_id отправьте боту любое сообщение и запросите /getUpdates.

Блокировка сетевых запросов. Симптом: curl или Invoke-RestMethod зависают или возвращают ошибку таймаута. Причина: межсетевой экран блокирует исходящие соединения к API мессенджеров. Решение: добавьте правило для скрипта или настройте прокси через переменные окружения http_proxy/https_proxy.

Права доступа к дискам. В Windows скрипт, запущенный от обычного пользователя, может не получить данные о некоторых томах. Запускайте задачу от имени SYSTEM или укажите учётную запись с административными правами в настройках Task Scheduler.

Синтаксические ошибки в скриптах. Для Bash выполните bash -n script.sh - это проверит синтаксис без запуска. Для PowerShell используйте powershell -NoProfile -Command "Get-Command -Syntax .\script.ps1". Всегда тестируйте скрипт вручную перед добавлением в cron или планировщик.

Файл-флаг не сбрасывается. Если после очистки диска флаг остаётся, оповещения перестают приходить при следующем заполнении. Убедитесь, что логика сброса флага корректна: в Bash-версии выше проверка выполняется во вложенном цикле, и переменная all_ok может не обновиться из-за подоболочки. Решение: вынесите проверку в отдельный проход без пайпа или используйте временный файл для хранения состояния.

Заключение: надёжный мониторинг за 15 минут

Вы получили готовые скрипты для Linux и Windows, которые проверяют свободное место на дисках и отправляют оповещения в Telegram, Slack или Email. Код содержит комментарии и легко адаптируется: измените порог, добавьте свои разделы, подключите дополнительный канал связи. Настройка cron или Task Scheduler занимает две минуты и превращает скрипт в полноценную систему мониторинга.

Для комплексного контроля инфраструктуры расширьте решение: подключите мониторинг загрузки файлов и сетевого трафика или настройте автоматическое резервное копирование со скриптами на Python и Bash. Если вы работаете с TrueNAS, посмотрите руководство по мониторингу репликации и Cloud Sync с уведомлениями в Telegram.

Разместите скрипты на своих серверах сегодня. 15 минут настройки избавят вас от ночных инцидентов и срочной очистки дисков вручную.

Поделиться:
Сохранить гайд? В закладки браузера