MAATRIX / Блог / Утренний обход сервера: пять команд, которые спасают выходные

Утренний обход сервера: пять команд, которые спасают выходные

MAATRIX

Почти каждая пятничная авария на самом деле начинается не в пятницу. Диск забивается логами не за час, бэкап перестаёт снимать дамп не в ночь перед проверкой, а неудачные попытки логина копятся в auth.log неделями — просто никто не смотрел. Ниже — не «внедрите Prometheus и Grafana», а рабочий минимум: пять проверок, которые занимают пару минут утром с чашкой кофе и снимают процентов восемьдесят внезапных аварий по выходным, пока не наступил полноценный мониторинг или пока он не нужен для одного-двух серверов.

Место на диске: где смотреть в первую очередь

df -h — первая команда, но не последняя. Она покажет процент занятости разделов, и если корень или /var перевалили за 85-90%, это уже повод разобраться, а не ждать 100%, когда сервис откажется писать логи или база — временные файлы.

df -h

Отдельно проверяйте инопы (inode) — раздел может быть забит под завязку миллионами мелких файлов при формально свободном месте:

df -i

Если место кончается, следующий шаг — не гадать, а быстро найти виновника. Классика — du по крупным каталогам:

du -sh /var/log/* 2>/dev/null | sort -rh | head -10
du -sh /var/lib/docker/* 2>/dev/null | sort -rh | head -10

На практике чаще всего виноваты три вещи: логи без ротации, старые docker-образы и слои (docker system df покажет разбивку), и файлы бэкапов, которые копятся локально перед отправкой во внешнее хранилище, а cron на отправку почему-то не отработал. Если у вас Docker — не забывайте, что du по каталогу контейнера не всегда покажет реальную картину логов контейнера; смотрите отдельно du -sh /var/lib/docker/containers/*/*-json.log.

Порог, после которого нужно действовать, а не откладывать: 80% — посмотреть, что растёт и с какой скоростью; 90% — разобраться сегодня, не после выходных. На забитом диске первым делом падает то, что чаще всего пишет: логи, временные файлы сортировки в базе, очереди сообщений — и происходит это обычно не в рабочее время, а ночью или в выходные, когда автоматика продолжает пытаться писать в никуда.

Память, своп и нагрузка: что тревожно, а что норма

free -h вызывает больше всего ложной паники: колонка available — не то же самое, что «свободно». Линукс активно использует память под дисковый кеш, и это нормально — кеш отдаётся приложениям по требованию. Смотреть нужно именно на available, а не на free.

free -h

Тревожный сигнал — не низкий free, а ненулевой и растущий swap. Разовое небольшое использование свопа при пиковой нагрузке — не катастрофа, но если swap used стабильно растёт день за днём без сброса, значит, приложению регулярно не хватает оперативной памяти, и рано или поздно это выльется в дикие тормоза или OOM killer, который прибьёт процесс не в самый удобный момент.

free -h | awk '/Swap/{print $3}'

Быстрый взгляд на нагрузку и очередь на CPU — uptime (load average за 1/5/15 минут) и vmstat 1 5 для тренда в реальном времени:

uptime
vmstat 1 5

Ориентир по load average для сервера с N ядрами: значение заметно выше N на протяжении долгого времени — сигнал, что процессор стал узким местом, а не разовым всплеском. Конкретные пороги у вас будут свои — они зависят от профиля нагрузки, поэтому важнее не абсолютное число, а его изменение день ото дня: одно дело — load average 2 на 4-ядерном сервере утром и вечером, другое — когда то же самое значение неделю назад было 0.5.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Статус ключевых сервисов одной командой

Отдельно проверять каждый сервис вручную — это то, что первым выпадает из утреннего ритуала, когда времени мало. Быстрее спросить у systemd список всего, что упало:

systemctl list-units --type=service --state=failed

Пустой вывод — хороший знак, но не гарантия: сервис может быть формально active, но не отвечать на запросы (завис, слушает порт, но не обрабатывает). Поэтому для критичных сервисов — веб-сервера, базы, очереди, VPN — стоит явно проверять именно их, а не полагаться на общий список:

systemctl is-active nginx postgresql redis-server wg-quick@wg0

Команда вернёт active для каждого работающего сервиса построчно (или inactive/failed — сразу видно, что не так). Для веб-сервисов не помешает добавить локальный HTTP-чек, который проверяет не «процесс жив», а «отвечает на запрос»:

curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/healthz

Если у приложения нет отдельного /healthz, подойдёт любой лёгкий эндпоинт, который точно требует прохождения через всё приложение, а не просто отдаёт статику. Разница принципиальная: systemctl is-active скажет, что процесс запущен, а curl — что он реально обслуживает трафик.

Свежесть бэкапа: дата в логе — это не бэкап

Это самая частая дыра из всех пяти пунктов, и статья о том, как скрипт бэкапа падал молча четыре месяца, — хороший пример того, к чему приводит проверка «cron отработал с кодом 0» вместо проверки «архив реально содержит данные». Код завершения 0 у скрипта в pipe ничего не говорит о том, что каждая команда в цепочке отработала успешно.

Минимальная проверка, которая ловит большинство случаев тихого отказа — свежесть файла и его размер, а не просто факт существования:

find /backup -name "*.sql.gz" -mtime -1 -printf "%f %s bytes\n"

Если находится файл младше суток и его размер в разумных пределах (сравнимо со вчерашним, а не в двадцать раз меньше) — уже неплохо. Для borgbackup или restic то же самое делается штатной командой со списком снапшотов и временем последнего:

borg list /path/to/repo --last 1 --format '{time} {archive}{NL}'
restic snapshots --latest 1

Порог тревоги — простой: последнего бэкапа не было больше 25-26 часов (с запасом на суточный цикл), либо размер архива внезапно упал на порядок относительно обычного. Оба сигнала дешевле проверить утром за десять секунд, чем узнать о них в момент, когда бэкап реально понадобился. Полноценный мониторинг именно бэкапов — отдельная тема, разобранная в статье про мониторинг бэкапов, но даже без него ручная проверка раз в день закрывает большую часть риска.

Failed-логины и подозрительная активность

Разовые неудачные попытки входа — это фон интернета, а не повод для паники: боты сканируют публичные IP на пароли постоянно, и в статье про бесполезный шум и реальный сигнал в брутфорсе по SSH разобрано, что стоит воспринимать всерьёз, а что — просто фоновый шум. Задача утренней проверки — не читать логи построчно, а поймать аномалию: резкий скачок числа попыток или успешный вход с незнакомого адреса.

Количество неудачных попыток за последние сутки (для Ubuntu/Debian — /var/log/auth.log, для систем на systemd — journalctl):

grep "Failed password" /var/log/auth.log | grep "$(date '+%b %e')" | wc -l
# или, если auth.log нет и логи только в journald:
journalctl -u ssh --since "24 hours ago" | grep -c "Failed password"

Если у вас стоит fail2ban — быстрый статус покажет, кто забанен прямо сейчас, и это заодно косвенно подтверждает, что сама защита жива и реагирует:

fail2ban-client status sshd

Список успешных входов за последние дни и текущие сессии — простая, но недооценённая проверка: если в списке есть логин или IP, которого быть не должно, это куда важнее сотни отбитых ботов:

last -a | head -20
who

Порог тревоги здесь качественный, а не количественный: не «сколько попыток», а «есть ли успешный вход не оттуда, откуда ожидается». Один успешный логин с незнакомого адреса важнее тысячи отбитых попыток подбора пароля.

От пяти команд к скрипту-дашборду за две минуты

Пять отдельных команд утром — уже неплохо, но человеческая память ненадёжна по понедельникам и в отпуске коллеги, который обычно это делал. Практичный следующий шаг — собрать все проверки в один скрипт, который выводит сводку одним экраном или присылает её в мессенджер. Вот рабочий каркас, который можно адаптировать под свой стек (список сервисов, путь к бэкапам и порог по диску — под себя):

#!/usr/bin/env bash
# morning-check.sh — утренний обход сервера

echo "=== Диск ==="
df -h --output=target,pcent,avail | grep -vE '^Filesystem|tmpfs|udev'

echo -e "\n=== Память и своп ==="
free -h | awk 'NR==1||NR==2||NR==3'

echo -e "\n=== Failed-сервисы ==="
systemctl list-units --type=service --state=failed --no-legend || echo "нет упавших"

echo -e "\n=== Ключевые сервисы ==="
for s in nginx postgresql redis-server wg-quick@wg0; do
  printf "%-20s %s\n" "$s" "$(systemctl is-active "$s" 2>/dev/null)"
done

echo -e "\n=== Последний бэкап ==="
find /backup -name "*.sql.gz" -mtime -1 -printf "%f (%s bytes)\n" || echo "СВЕЖЕГО БЭКАПА НЕТ"

echo -e "\n=== Failed-логины за сутки ==="
grep "Failed password" /var/log/auth.log 2>/dev/null | grep "$(date '+%b %e')" | wc -l

echo -e "\n=== Load average ==="
uptime

Дальше — вопрос вкуса и масштаба. Для одного-двух серверов достаточно повесить скрипт в cron на 8 утра с выводом на почту (MAILTO в crontab) или отправкой в Telegram-бота одной curl-командой к Bot API. Для десятка серверов уже разумнее не изобретать велосипед, а взять готовый мониторинг — Zabbix, Netdata или связку Prometheus + Grafana с алертами; ручной скрипт хорош как временное решение или как страховочная сетка поверх основного мониторинга, а не как его замена. Отдельно стоит подключить внешний heartbeat-пинг вроде Healthchecks.io на сам факт запуска скрипта — если скрипт-дашборд сам перестанет запускаться, вы должны узнать об этом тоже, а не только по тишине в почте.

Ключевая идея не в конкретных командах, а в привычке: одна и та же проверка каждое утро, в одно и то же время, без исключений «сегодня некогда». Именно нерегулярность делает утренний обход бесполезным — пропущенные два-три дня подряд превращаются в тот самый зазор, где авария успевает созреть незаметно.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Сколько реально занимает утренний обход, если делать его руками?

При одном сервере и заученных командах — минуту-полторы, если ничего не сломано. С готовым скриптом-дашбордом — время чтения одного экрана вывода, секунд двадцать-тридцать.

Нужен ли этот ритуал, если уже есть Zabbix или Grafana с алертами?

Да, но в урезанном виде — он не заменяет мониторинг с историей и графиками, а работает как быстрая ручная сверка «глазами», которая иногда ловит то, на что алерт не настроен, и приучает читать сырые данные, а не только дашборды.

Что делать, если скрипт-дашборд показывает тревожный признак, но сервис вроде бы работает?

Разбираться сразу, не откладывать до понедельника — большинство инцидентов из разряда «мы это видели неделю назад, но работало же» на самом деле уже деградировали, просто медленно и незаметно для пользователей.

Стоит ли автоматически рассылать вывод скрипта в Telegram или почту каждое утро?

Да, если проверка выполняется не вами лично каждый раз — рассылка снимает риск забыть запустить скрипт руками, но не должна быть безусловной: имеет смысл слать полный отчёт только при отклонении от нормы, а не спамить одинаковым «всё ок» каждый день, иначе отчёты быстро начнут игнорировать.

Как часто менять пороги (80% диска, 25 часов для бэкапа и так далее)?

Раз в несколько месяцев, когда меняется профиль нагрузки — например, вы добавили сервис, который пишет больше логов, или база выросла и дампы стали занимать больше места. Жёстко зашитые в скрипт цифры полезно пересматривать вместе с ростом проекта, а не оставлять навсегда.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →