Простой мониторинг сервера штатными средствами системы
Скрипт проверки, systemd-таймер и проверенный канал уведомлений закрывают потребности одиночного root-сервера. Руководство показывает, что стоит мониторить, как проверить каждый шаг и с какого момента окупается большой инструментарий.
Сервер не сообщает о себе сам, когда что-то идёт не так. Он работает, пока не перестаёт работать, а первая обратная связь приходит от клиента или от вас, если вы случайно туда посмотрели. Это руководство собирает минимальный мониторинг, который кладёт этому конец: скрипт проверки, systemd-таймер, канал уведомлений. Без базы данных временных рядов, без панели мониторинга, без единого дополнительного открытого порта.
Все сведения относятся к Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS и Ubuntu 22.04 LTS. Там, где эти четыре системы расходятся, об этом сказано отдельно. Все команды написаны для работы от имени root; обычному пользователю нужно ставить перед каждой командой sudo. Это руководство подробно разбирает шаг 8 из чек-листа по настройке нового root-сервера.
Что вообще стоит мониторить
Самая частая ошибка на первом мониторинге не в том, что измеряют слишком мало, а в том, что измеряют слишком много. Тот, кто собирает 40 показателей, не смотрит ни на один из них. Смысл есть только в том, что способно остановить работу и на что вы можете отреагировать. Остаётся семь пунктов.
| Показатель | Почему он в списке | Откуда берётся значение | Разумный порог |
|---|---|---|---|
| Место на накопителе | Самая частая причина отказа, которую никто не видит заранее | df --output=pcent,target | от 85% |
| Inodes | Место как будто есть, и всё равно «No space left on device» | df --output=ipcent,target | от 85% |
| Свободная оперативная память | OOM-killer редко выбирает тот процесс, которым вы готовы пожертвовать | MemAvailable в /proc/meminfo | меньше 200 МБ |
| Средняя нагрузка | Показывает затор независимо от того, виноват CPU или накопитель | третье поле в /proc/loadavg | среднее за 15 минут выше удвоенного числа ядер |
| Упавшие службы | Служба, умершая ночью, иначе пролежит мёртвой до утра | systemctl is-system-running | всё, кроме running |
| Истечение сертификата | Разом отсекает каждого посетителя, а не часть | openssl x509 -checkend | меньше 21 дня до конца срока |
| Доступность снаружи | Единственная проверка, отвечающая на вопрос, жив ли сервер | второй хост, curl | два сбоя подряд |
В списке нет загрузки CPU в процентах: сервер, который выдаёт 100%, потому что на нём работает видеокодировщик, делает ровно то, для чего его поставили. По той же причине нет пропускной способности сети и количества процессов. И то и другое помогает искать причину, но не годится в качестве оповещения, потому что не существует значения, начиная с которого вы обязаны вмешаться.
Путь назад, ещё до первого файла
Мониторинг только читает и в обычном случае ничего сломать не может. Три вещи всё же могут.
Скрипт, который чинит вместо того, чтобы сообщать. Мысль соблазнительная: если nginx умер, пусть скрипт его просто перезапустит. Получается служба, которая стартует каждые десять минут, работает полсекунды и прячет настоящую причину. А скрипт, который при заполненном накопителе удаляет файлы самостоятельно, рано или поздно удалит что-то нужное. Первая версия только читает и не вызывает ни systemctl restart, ни rm, ни kill.
Открытые сетевые интерфейсы. Экспортёры метрик, которые слушают на всех адресах, — одна из самых частых непреднамеренных публикаций данных на одиночных серверах. Описанный здесь способ не открывает ни одного порта и не требует правила файрвола.
Сам канал оповещения. Мониторинг, уведомление которого ни разу не проверяли, — это не мониторинг, а приятное чувство уверенности. Проверка описана ниже, и она обязательна.
Как попасть на сервер без SSH
У KVM root-серверов и выделенных серверов нет ни IPMI, ни iDRAC. Если SSH перестал отвечать, вход остаётся один: VNC-консоль в личном кабинете. Она не завязана на сетевой стек гостевой системы, поэтому ни правило файрвола, ни перегруженная служба SSH её не заблокируют. Зайдите туда один раз заранее и убедитесь, что знаете пароль root.
Аварийный выключатель
Если сам мониторинг превратится в проблему, например начнёт слать оповещения каждую минуту, вам понадобятся две команды. Запомните их прежде, чем начнёте:
systemctl disable --now kh-monitor.timer
systemctl mask kh-monitor.service
Первая немедленно останавливает таймер и не даёт ему вернуться при следующей загрузке. Вторая — это стоп-кран: замаскированную службу не получится случайно запустить и вручную, а отменяется маскировка командой systemctl unmask kh-monitor.service. Способ малорискованный прежде всего потому, что появляются исключительно новые файлы; откат сводится к удалению этих файлов. И всё же держите открытой вторую SSH-сессию, пока работаете с системой.
Сначала проверьте показатели вручную
Прежде чем скрипт начнёт что-то оценивать, каждое значение стоит хотя бы раз увидеть своими глазами. Иначе позже вы не поймёте, обоснованное это оповещение или просто порог выставлен бессмысленно.
Место на накопителе и inodes
df -h
df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay
df -i
Исключения здесь необходимы. В Ubuntu 22.04 и 24.04 snap подключает свои пакеты как squashfs-образы только для чтения, и они постоянно показывают 100%. Без -x squashfs ваш мониторинг начиная с первого же запуска будет сообщать о заполненном накопителе, каждый день, бесконечно. То же самое относится к overlay-точкам монтирования Docker.
Стоит знать две особенности. df не принимает -P и --output вместе и завершается сообщением о взаимоисключающих параметрах. А на ext4 по умолчанию пять процентов зарезервированы для root, поэтому df показывает уже 100%, пока root ещё может писать. Что делать после оповещения, описано в статье Диск заполнен в Linux.
Проверка inodes не второстепенная мелочь. Каталог с миллионами крошечных сессионных или кэш-файлов способен израсходовать все inodes, пока df -h показывает вдоволь свободного места. Запись тогда падает с ошибкой No space left on device, и самое очевидное объяснение оказывается неверным.
Оперативная память
free -m
awk '/^MemAvailable:/ { printf "%d MB\n", $2 / 1024 }' /proc/meminfo
Столбец free на здоровой Linux-системе почти всегда маленький, потому что ядро использует незанятую память под файловый кэш. Доверять можно только столбцу available, то есть значению MemAvailable: это объём памяти, который может получить новое приложение без вытеснения чего-либо в swap. Оповещайте по этому значению, а не по free.
Было ли уже туго раньше, покажет журнал ядра:
journalctl -k -b --grep "Out of memory"
Каждое совпадение — это процесс, который ядро завершило из-за нехватки памяти. Как на это реагировать, не создавая swap вслепую, описано в статье Out of Memory и правильная настройка swap.
Средняя нагрузка
nproc
cat /proc/loadavg
uptime
Первые три поля в /proc/loadavg — это средние значения за одну, пять и пятнадцать минут. Два момента понимают неправильно постоянно. Во-первых, нагрузка в Linux не является чисто процессорной величиной: процессы, ожидающие обращения к накопителю, тоже учитываются. Нагрузка 20 на четырёх ядрах может означать и что CPU горит, и что подтормаживает накопитель. Во-вторых, значение за одну минуту не годится для оповещений, потому что любой прогон резервного копирования ненадолго подбрасывает его вверх. Берите среднее за 15 минут, а порог задавайте относительно числа ядер.
Если ваше ядро приносит с собой статистику заторов, она информативнее, потому что показывает CPU, ввод-вывод и память по отдельности. Есть она не везде:
test -d /proc/pressure && cat /proc/pressure/io || echo "в этом ядре нет статистики заторов"
Службы
systemctl is-system-running
systemctl --failed --no-pager
systemctl is-active nginx
systemctl is-system-running — самая короткая осмысленная общая проверка. Она выводит running, если ни один юнит не находится в состоянии ошибки, и degraded, как только такой юнит появляется. Код возврата соответственно 0 или отличный от нуля.
Две ловушки. Состояние degraded сохраняется до тех пор, пока вы после ремонта не сбросите его командой systemctl reset-failed; иначе один раз упавшая задача держит это сообщение неделями. А при проверке отдельных служб системы расходятся: в Ubuntu 24.04 SSH запускается через активацию по сокету, и ssh.service в состоянии покоя там inactive, хотя SSH прекрасно доступен. Кто мониторит там ssh.service, получает постоянный ложный сигнал. В Ubuntu 24.04 наблюдать нужно за ssh.socket, а в Debian 12, Debian 13 и Ubuntu 22.04, наоборот, за ssh.service.
Истечение сертификата
openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem
openssl x509 -checkend 1814400 -noout -in /etc/letsencrypt/live/example.com/fullchain.pem
Интереснее вторая команда. -checkend ожидает количество секунд, 1814400 — это 21 день. Если сертификат истекает в этот срок, команда выводит Certificate will expire и возвращает код 1, иначе Certificate will not expire и 0. Каталоги /etc/letsencrypt/live и /etc/letsencrypt/archive доступны на чтение только пользователю root.
У этой проверки есть пробел, о котором многие руководства умалчивают: она проверяет файл на диске, а не сертификат, который отдаёт ваш веб-сервер. Если продление прошло, но перезагрузка конфигурации веб-сервера сорвалась, файл новый, а ключ отдаётся старый. Проверка файла молчит, а посетители уже видят предупреждение о сертификате. Такой случай ловит только взгляд снаружи:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate
-servername перестаёт быть необязательным, как только на одном IP-адресе лежит несколько сертификатов. Без этого параметра вы получите сертификат сервера по умолчанию и проверите не тот домен.
Скрипт проверки
Все проверки вместе складываются в скрипт, который только читает, сравнивает и сообщает, когда что-то не так. Ему нужны curl и, для отправки через webhook, jq. В минимальных установках Debian нет ни того, ни другого:
apt update
apt install -y curl jq
cat > /usr/local/sbin/kh-monitor <<'EOF'
#!/bin/bash
set -u
DISK_WARN="${DISK_WARN:-85}"
INODE_WARN="${INODE_WARN:-85}"
MEM_MIN_MB="${MEM_MIN_MB:-200}"
LOAD_FACTOR="${LOAD_FACTOR:-2}"
CERT_DAYS="${CERT_DAYS:-21}"
UNITS="${UNITS:-ssh nginx}"
STATE_DIR="${STATE_DIRECTORY:-/var/lib/kh-monitor}"
problems=""
add() { problems+="- ${1}"$'\n'; }
notify() {
printf '%s | %s\n' "$1" "$(printf '%s' "$2" | tr '\n' ' ')"
if [ -n "${WEBHOOK_URL:-}" ]; then
printf '%s\n%s' "$1" "$2" | jq -Rs '{text: .}' \
| curl -fsS -m 10 -o /dev/null -H 'Content-Type: application/json' \
--data-binary @- "$WEBHOOK_URL"
fi
if [ -n "${MAILTO:-}" ]; then
printf '%s\n' "$2" | mail -s "$1" "$MAILTO"
fi
}
while read -r pcent target; do
pcent="${pcent%\%}"
case "$pcent" in ''|*[!0-9]*) continue ;; esac
[ "$pcent" -ge "$DISK_WARN" ] && add "Накопитель ${target} заполнен на ${pcent}%"
done < <(df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay | tail -n +2)
while read -r ipcent target; do
ipcent="${ipcent%\%}"
case "$ipcent" in ''|*[!0-9]*) continue ;; esac
[ "$ipcent" -ge "$INODE_WARN" ] && add "Inodes на ${target} заняты на ${ipcent}%"
done < <(df --output=ipcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay | tail -n +2)
mem_avail=$(awk '/^MemAvailable:/ { printf "%d", $2 / 1024 }' /proc/meminfo)
[ "${mem_avail:-0}" -lt "$MEM_MIN_MB" ] && add "Доступно всего ${mem_avail} МБ оперативной памяти"
cores=$(nproc)
load15=$(awk '{ print $3 }' /proc/loadavg)
awk -v l="$load15" -v c="$cores" -v f="$LOAD_FACTOR" 'BEGIN { exit !(l > c * f) }' \
&& add "Средняя нагрузка за 15 минут ${load15} при ${cores} ядрах"
sysstate=$(systemctl is-system-running)
[ "$sysstate" = "running" ] || add "systemd сообщает о состоянии ${sysstate}"
for unit in $UNITS; do
systemctl is-active --quiet "$unit" || add "Служба ${unit} в состоянии $(systemctl is-active "$unit")"
done
for cert in /etc/letsencrypt/live/*/fullchain.pem; do
[ -r "$cert" ] || continue
openssl x509 -checkend $(( CERT_DAYS * 86400 )) -noout -in "$cert" >/dev/null 2>&1 \
|| add "Сертификат ${cert} истекает менее чем через ${CERT_DAYS} дней"
done
mkdir -p "$STATE_DIR"
now=$(printf '%s' "$problems" | sha256sum | cut -d' ' -f1)
before=$(cat "${STATE_DIR}/last" 2>/dev/null || true)
printf '%s' "$now" > "${STATE_DIR}/last"
if [ -z "$problems" ]; then
[ -n "${HEARTBEAT_URL:-}" ] && curl -fsS -m 10 -o /dev/null "$HEARTBEAT_URL"
[ -n "$before" ] && [ "$now" != "$before" ] \
&& notify "Отбой тревоги $(hostname -s)" "Все проверки снова без замечаний."
exit 0
fi
[ "$now" = "$before" ] && exit 0
notify "Предупреждение $(hostname -s)" "$problems"
EOF
Четыре места заслуживают пояснения.
- Циклы читают из
< <( ... ), а не из конвейера. Конвейер переносит цикл в subshell, и собранные там сообщения пропали бы послеdone. Ошибка коварная, потому что скрипт отрабатывает без сбоев и просто никогда ни о чём не сообщает. - Пороги читаются из окружения. Любой предел можно переопределить для одного отдельного вызова. На этом и построена проверка оповещения ниже.
- Состояние сохраняется в виде контрольной суммы. Сообщение уходит только тогда, когда список проблем изменился. Иначе заполненный накопитель будет каждые десять минут присылать вам одно и то же, и через два дня вы выключите мониторинг.
- Цикл по сертификатам уходит вхолостую, если каталога Let's Encrypt нет. Шаблон остаётся нераскрытым,
[ -r "$cert" ]не срабатывает, и итерация пропускается.
Проверьте сейчас, пока в игру не вступил systemd:
chmod 700 /usr/local/sbin/kh-monitor
bash -n /usr/local/sbin/kh-monitor && echo "Синтаксис в порядке"
/usr/local/sbin/kh-monitor; echo "Код возврата $?"
На здоровом сервере третья команда не выводит ничего, кроме Код возврата 0. Если вы видите сообщение, значит либо что-то действительно не в порядке, либо порог подобран неудачно, например потому, что в UNITS указана служба, которой на этой машине нет.
systemd-таймер
Cron-задание тоже подошло бы. Но у таймера четыре конкретных преимущества: он не запускает второй экземпляр, пока работает первый, он навёрстывает пропущенный запуск после перезагрузки, его вывод попадает в журнал, и отключается он одной командой. Юниту службы не нужен раздел [Install], потому что активирует его не запуск системы, а таймер.
cat > /etc/systemd/system/kh-monitor.service <<'EOF'
[Unit]
Description=Короткая проверка состояния сервера
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/kh-monitor
EnvironmentFile=-/etc/default/kh-monitor
StateDirectory=kh-monitor
SyslogIdentifier=kh-monitor
Nice=10
IOSchedulingClass=idle
EOF
cat > /etc/systemd/system/kh-monitor.timer <<'EOF'
[Unit]
Description=Регулярно запускает kh-monitor
[Timer]
OnCalendar=*:0/10
RandomizedDelaySec=60
Persistent=true
[Install]
WantedBy=timers.target
EOF
StateDirectory=kh-monitor создаёт /var/lib/kh-monitor с подходящими правами и задаёт переменную STATE_DIRECTORY, к которой обращается скрипт. Знак минуса перед путём в EnvironmentFile=-/etc/default/kh-monitor означает, что отсутствующий файл не считается ошибкой. RandomizedDelaySec=60 разбрасывает момент старта, а Persistent=true при загрузке навёрстывает запуск, пропущенный во время выключения.
Таймер автоматически активирует одноимённую службу, строка Unit= не нужна:
systemd-analyze verify /etc/systemd/system/kh-monitor.service
systemd-analyze calendar '*:0/10'
systemctl daemon-reload
systemctl start kh-monitor.service
systemctl enable --now kh-monitor.timer
Проверка результата:
systemctl list-timers kh-monitor.timer --no-pager
journalctl -u kh-monitor.service -n 20 --no-pager
Список обязан показать строку со временем следующего запуска. Если он пуст, таймер не активен. systemd-analyze calendar находит опечатки во временном выражении: он приводит его к нормальной форме и называет ближайший срок. Подробности о юнит-файлах и их типичных неисправностях описаны в статье Создание systemd-службы.
Канал уведомлений
Здесь и разваливается большинство самодельных систем мониторинга. Сообщающая часть работает на том самом сервере, за которым следит, а значит падает вместе с ним. В итоге она надёжно сообщает обо всём, кроме единственного случая, который действительно важен.
Ответ на это — сигнал жизни, то есть heartbeat: сервер после каждого удачного прогона отмечается на внешней стороне, а если отметка не приходит, внешняя сторона поднимает тревогу. Скрипт выше делает именно это, когда задана переменная HEARTBEAT_URL. Обрыв сети, зависшая файловая система и рухнувшая система выглядят для внешней стороны одинаково, и знать вы хотите про все три случая.
Учётные данные должны лежать в отдельном файле, а не в скрипте. Адрес webhook — это секрет: у кого он есть, тот может отправлять сообщения от вашего имени:
cat > /etc/default/kh-monitor <<'EOF'
WEBHOOK_URL=https://example.example/hooks/xxxxxxxx
HEARTBEAT_URL=https://example.example/heartbeat/xxxxxxxx
UNITS="ssh nginx"
EOF
chmod 600 /etc/default/kh-monitor
Кавычки вокруг UNITS важны: systemd обошёлся бы и без них, но при тестовом прогоне ниже файл читает shell, и там nginx без кавычек был бы воспринят как команда. Вписывайте только те юниты, которые на этой системе есть, то есть в Ubuntu 24.04 ssh.socket вместо ssh.
Кому больше нравится электронная почта, тому нужен способ отправки. Полноценный почтовый сервер здесь избыточен, достаточно простого пересыльщика:
apt install -y msmtp msmtp-mta bsd-mailx
Настраивается это в /etc/msmtprc с учётными данными существующего почтового ящика. Файл содержит пароль, поэтому ему полагается chmod 600, иначе msmtp откажется работать и сошлётся на права доступа. Два честных ограничения: письмо с только что выданного IP-адреса сервера часто попадает в спам или отклоняется, а сообщение, которое вы увидите только при следующем заходе в почту, при отказе приходит слишком поздно. Для оповещений push-доставка практичнее.
Вызовите оповещение один раз вручную
Этот шаг обязателен. Вызовите сообщение принудительно, задав для одного отдельного вызова заведомо бессмысленный порог:
set -a; . /etc/default/kh-monitor; set +a
DISK_WARN=0 /usr/local/sbin/kh-monitor
rm -f /var/lib/kh-monitor/last
Сообщение теперь должно действительно дойти до вас, а не просто оказаться в журнале. Третья строка удаляет сохранённое состояние, чтобы тестовое оповещение не подавило следующий настоящий прогон. Один побочный эффект задуман нарочно: если доставка сорвётся, kh-monitor.service завершится с ошибкой и попадёт в systemctl --failed. Молчащий канал уведомлений был бы худшей из мыслимых неисправностей в системе мониторинга.
Взгляд снаружи
Сигнал жизни говорит вам, что сервер жив. Он не говорит, что ваш сайт отвечает. Для этого нужна проверка с другой площадки, по той же схеме из скрипта и таймера, только на втором хосте:
curl -fsS -m 10 -o /dev/null -w '%{http_code} %{time_total}\n' https://example.com/
Ценность этой проверки определяют четыре момента. Первое: проверяйте настоящую службу, а не только ICMP. Сервер, который отвечает на ping, пока веб-сервер висит в бесконечном цикле, при проверке пингом считается здоровым. Второе: -f заставляет curl завершаться с ошибкой при кодах ошибок HTTP, без этого ключа страница ошибки тоже засчитывается как успех. Третье: поднимайте тревогу только после двух неудач подряд, иначе о простое отчитается любая короткая сетевая помеха. Четвёртое: вызов раз в минуту с одного и того же адреса может упереться в ограничение частоты запросов или быть расценен блокирующим программным обеспечением как атака; внесите адрес проверяющего хоста в исключения.
Если второго сервера нет, остаётся внешний сервис проверки. Бесплатные предложения проверяют обычно раз в пять минут, о простое вы узнаете с соответствующей задержкой. Для одного сервера этого хватает, и это лучше, чем альтернатива: не узнать вовсе.
Частые ошибки и решения
Failed to start kh-monitor.service: Unit kh-monitor.service not found.: после создания или изменения юнита не хватает systemctl daemon-reload. Вторая по частоте причина — неверный каталог; собственные юниты кладутся в /etc/systemd/system/.
The unit files have no installation config: вы вызвали systemctl enable kh-monitor.service вместо kh-monitor.timer. У службы намеренно нет раздела [Install], включать нужно таймер.
code=exited, status=203/EXEC: systemd не смог выполнить файл. Либо неверен путь в ExecStart, либо не сделан chmod 700, либо файл правили в Windows и он несёт концы строк с возвратом каретки. Против этого помогает sed -i 's/\r$//' /usr/local/sbin/kh-monitor.
Syntax error: redirection unexpected: скрипт запустили через sh, а не через bash. В Debian и Ubuntu /bin/sh — это оболочка dash, а она не знает ни < <( ... ), ни += для строк. Первая строка обязана быть #!/bin/bash.
bash: mail: command not found: почтовая программа не установлена. Команда mail в зависимости от системы приходит из bsd-mailx или mailutils, и наборы ключей у них различаются. Держитесь -s для темы письма.
curl: (22) The requested URL returned error: 404: адрес webhook неверен или удалён на принимающей стороне. Без -f curl проглотил бы эту ошибку молча.
curl: (60) SSL certificate problem: certificate has expired: при проверке снаружи это не сбой инструмента, а именно тот результат, который искали. При обращении к собственному webhook то же сообщение указывает на неверное время на проверяющем сервере.
Certificate will expire: штатный вывод openssl x509 -checkend с кодом возврата 1. Проверьте, работает ли ещё продление и перезагружается ли после него веб-сервер.
Failed to parse calendar specification: выражение после OnCalendar= недопустимо. Проверьте его отдельно командой systemd-analyze calendar, прежде чем переносить в юнит.
Warning: Stopping kh-monitor.service, but it can still be activated by: kh-monitor.timer: вы остановили службу вместо таймера. Служба и так работает лишь секунды, отключать нужно таймер.
Оповещение при каждом прогоне, хотя ничего не изменилось: состояние не сохраняется. Проверьте, есть ли в юните строка StateDirectory=kh-monitor и существует ли /var/lib/kh-monitor/last с правом на запись.
Оповещения нет, хотя что-то явно сломано: вызовите принудительное сообщение из раздела выше. Если и оно не приходит, дело в канале доставки, а не в проверках.
Различия между четырьмя системами
| Система | Какой SSH-юнит мониторить | Точки монтирования squashfs | Куда попадают сообщения |
|---|---|---|---|
| Debian 13 (trixie) | ssh.service, отдельные образы используют ssh.socket | как правило, нет | только журнал, в минимальных установках rsyslog отсутствует |
| Debian 12 (bookworm) | ssh.service | как правило, нет | журнал, rsyslog в зависимости от варианта установки |
| Ubuntu 24.04 LTS | ssh.socket | обычно есть, нужно исключение | журнал и rsyslog |
| Ubuntu 22.04 LTS | ssh.service | обычно есть, нужно исключение | журнал и rsyslog |
На всех четырёх системах одинаково: systemd-analyze, StateDirectory= и RandomizedDelaySec= есть везде, скрипт и юнит-файлы работают без изменений.
Когда окупается большой инструментарий
У того, что у вас теперь есть, чёткие границы. История не сохраняется, поэтому нельзя посмотреть, растёт ли потребление памяти последние три недели. Корреляции между несколькими хостами тоже нет. И нет ни эскалации, ни правил дежурства, ни возможности заглушить известное оповещение на два часа.
Именно эти пункты и отвечают на вопрос о переходе. Связка сбора метрик и панели мониторинга окупается, как только выполняется хотя бы одно из условий:
- Вы держите больше горстки серверов и хотите видеть их рядом друг с другом.
- Вам нужны история и тренды, например для планирования мощностей или чтобы ответить цифрами на жалобу о медленной работе.
- Дежурство делят несколько человек, а значит нужны уровни эскалации и заглушение оповещений.
- Вам нужно подтверждать доступность перед третьей стороной.
Если ничего из этого не подходит, для одиночного сервера такая конструкция обычно невыгодна. Сборщик, база данных, панель мониторинга и экспортёр вместе легко занимают несколько сотен мегабайт оперативной памяти на той самой машине, свободную память которой они должны наблюдать. К этому добавляются ещё один открытый порт и второе программное обеспечение, которое требует обновлений. Решающий момент остаётся прежним: если сборщик работает на том же сервере, о его отказе он сообщит ровно так же плохо, как скрипт. При переходе сборщик уносят на другой хост, а экспортёр привязывают к 127.0.0.1 или ограничивают файрволом до его адреса.
Средний путь работает хорошо: таймер и скрипт остаются, потому что закрывают случай тревоги, а сбор метрик добавляется тогда, когда понадобится история. Одно другому не мешает.
Откат
Если захотите избавиться от всей этой конструкции, понадобится пять строк:
systemctl disable --now kh-monitor.timer
rm -f /etc/systemd/system/kh-monitor.timer /etc/systemd/system/kh-monitor.service
rm -f /usr/local/sbin/kh-monitor /etc/default/kh-monitor
rm -rf /var/lib/kh-monitor
systemctl daemon-reload
Итоговая проверка
Шесть проверок, которые показывают действительное состояние, а не то, на которое вы надеетесь:
systemctl list-timers kh-monitor.timer --no-pagerназывает время следующего запуска.journalctl -u kh-monitor.service --since "1 hour ago" --no-pagerпоказывает прогоны с ожидаемым интервалом.- Принудительное оповещение через
DISK_WARN=0доходит до вас, а не остаётся только в журнале. - После
rebootтаймер продолжает работать без каких-либо действий с вашей стороны. - Сигнал жизни срабатывает: остановите таймер и подождите, поднимет ли внешняя сторона тревогу.
systemctl --failed --no-pagerне перечисляет ничего, и прежде всего неkh-monitor.service.
Пятый пункт самый неудобный и самый важный. Мониторинг, у которого тревожный случай ни разу не наступал, — это предположение. Только после того, как вы намеренно вызвали отказ и получили сообщение, цепочка от сервера до вашего телефона доказуемо целая.
Частые вопросы
Действительно ли для одиночного root-сервера нужен сервер метрик с панелью мониторинга?
Почему systemd-таймер, а не cron-задание?
Мониторинг постоянно сообщает о заполненном накопителе, хотя места достаточно. В чём дело?
Как я узнаю, что сервер отказал полностью?
За каким SSH-юнитом нужно следить?
Как избавиться от одного и того же предупреждения каждые десять минут?
Сертификат на диске действителен, а посетители всё равно видят предупреждение. Как так получается?
Как быстро отключить мониторинг, если он мешает?
2026 KernelHost GmbH. Все права защищены. Эта инструкция охраняется авторским правом. Публикация на других сайтах, в том числе частично или в изменённом виде, без нашего письменного согласия не разрешается. Цитирование с указанием источника и активной ссылкой мы приветствуем.

