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