Сервер редко отказывает внезапно. Сначала несколько месяцев тихо растёт занятое место на разделе, потом задание резервного копирования второй раз подряд завершается с ошибкой, потом накопитель начинает выдавать переназначенные сектора, и только когда сдвиги складываются в одну кучу, приходит отказ. Месячный цикл обслуживания закрывает именно медленную деградацию: она незаметна день ото дня, но хорошо видна на дистанции в четыре недели.
Смысл цикла в том, чтобы раз в месяц возвращать сервер в известное состояние, а каждое отклонение фиксировать в протоколе. Проверять всё подряд не нужно, у мониторинга своя работа и свой темп. Ниже разобран набор действий, закрывающий медленные процессы: обновления, копии, место, накопители, учётные записи, сертификаты, службы и сеть. Каркас месячного прогона умещается в один список:
- проверить и установить обновления безопасности, при смене ядра согласовать перезагрузку в плановое окно;
- убедиться, что задания резервного копирования за месяц прошли успешно, и выполнить выборочное восстановление;
- проверить свободное место по разделам, почистить старые журналы и временные файлы, убедиться в работе ротации;
- снять показания самодиагностики накопителей, сверить температуры и просмотреть ошибки ядра за месяц;
- провести ревизию учётных записей, возраста паролей и административных доступов;
- проверить сроки действия сертификатов и ключей, внести даты перевыпуска в календарь;
- просмотреть незапланированные перезапуски и ошибки служб, сверить слушающие порты и правила фильтрации;
- записать результаты и изменения месяца в протокол обслуживания.
Дальше каждый пункт раскрыт с командами и рабочими деталями.
Обновления безопасности и плановая перезагрузка после смены ядра
Обновления безопасности стоят в списке первыми не случайно: незакрытая уязвимость сетевой службы доступна извне круглосуточно, остальные пункты спокойно подождут час. На Debian и Ubuntu базовая последовательность знакома каждому:
apt update
apt list --upgradable
apt upgrade
На сервере под действующей нагрузкой ставят чаще только исправления безопасности. Пакет unattended-upgrades делает это автоматически по расписанию, его настраивают один раз:
apt-get install unattended-upgrades
В файле /etc/apt/apt.conf.d/50unattended-upgrades задаётся, какие репозитории использовать: только security-источник или всё сразу. В семействе RHEL та же логика через dnf:
dnf check-update
dnf upgrade --security
С ядром история отдельная. После его обновления в памяти продолжает работать старая версия, и уязвимость остаётся открытой, хотя обновление уже установлено. На Ubuntu после обновлений, требующих рестарта, появляется файл /var/run/reboot-required, проверить его достаточно командой cat. На RHEL ответ даёт команда needs-restarting с ключом -r из пакета dnf-plugins-core. Полезна и утилита needrestart: она перечисляет службы, которые после обновления библиотек продолжают работать со старыми версиями, и подсказывает, что перезапускать первым делом.
Перезагрузку не делают "когда-нибудь": под неё выделяют плановое окно, согласованное с командой и пользователями. Разница между "перезагрузим в среду ночью" и "перезагрузим, когда будет минутка" превращается в разницу между плановым обслуживанием и внеплановым простоем. Команда shutdown -r 22:30 ставит рестарт на точное время, а подключённым пользователям уходит сообщение с причиной. У Canonical есть сервис Livepatch по подписке Ubuntu Pro: он накладывает критические исправления ядра на работающую систему и откладывает перезагрузку, но полного обновления без рестарта не отменяет.
После перезагрузки проверяют три вещи: uptime -s покажет фактическое время старта системы, uname -r подтвердит новое ядро, systemctl --failed выявит службы, не поднявшиеся обратно. Всё, что не сошлось, уходит в протокол в тот же день, пока детали свежи.
Контроль резервных копий за месяц и выборочный тест восстановления
Резервная копия, которую ни разу не восстанавливали, остаётся предположением. До первого восстановления это набор файлов, про который кто-то когда-то сказал, что он годится для возврата данных. Месячный контроль копий состоит из трёх частей: история заданий, место в хранилище и выборочный тест.
Начинают с истории заданий. Если копирование запущено через systemd-таймер, всё просто:
systemctl list-timers --all
journalctl -u restic-backup.service --since "30 days ago"
В журнале ищут ошибки и ночные сводки. Инструменты помогают сами: restic печатает сводку добавленных и изменённых файлов, borg хранит список архивов с датами, rsnapshot пишет отчёт в /var/log/rsnapshot.log. Смотреть нужно не только факт успеха, но и объём: если ночная копия внезапно похудела в десять раз, значит, изменилось поведение задания, и чаще всего причина в забытом смонтированном разделе или расширившемся исключении в маске файлов.
Дальше смотрят хранилище копий. На хосте с резервами выполняют df -h /srv/backup и сравнивают цифры с прошлым месяцем. Рост должен быть предсказуемым: база прибавляет известный объём, логи известный, скачок на треть раздела за месяц требует разбирательства. У restic есть собственная проверка целостности:
restic check --read-data-subset=5%
Команда проверяет структуру репозитория и читает случайные 5% содержимого, сверяя контрольные суммы. Полное чтение оставляют на квартал, для месяца достаточно выборки.
Третья часть - тест восстановления. Из свежего архива возвращают один небольшой файл в отдельный каталог и сверяют результат:
restic restore latest --target /tmp/restore-test --include /etc/nginx/nginx.conf
diff /tmp/restore-test/etc/nginx/nginx.conf /etc/nginx/nginx.conf
С дампами баз схема та же: архив разворачивают во временную базу и выполняют пару выборочных запросов. Для файловых архивов достаточно сверки контрольных сумм. Дата теста, имя архивной копии и результат попадают в протокол. Пять минут работы в месяц закрывают вопрос, на который иначе отвечают только во время аварии, и тогда цену ответа назначает сама авария.
Место на разделах, чистка старых журналов и работа ротации
Место на диске кончается по-разному: иногда честно заполняется раздел, иногда исчерпываются inodes при полупустом выводе df. Поэтому смотрят обе картины:
df -h
df -i
Крупных потребителей ищут сверху вниз:
du -h --max-depth=1 /var 2>/dev/null | sort -h | tail -20
В интерактивном режиме удобен ncdu: он показывает те же цифры и позволяет сразу просмотреть подозрительный каталог. Стабильный набор пожирателей места известен каждому: журналы, временные файлы, кэш пакетного менеджера, старые ядра, образы контейнеров.
Журнал systemd растёт незаметно, его объём проверяют одной командой:
journalctl --disk-usage
Лимит задаётся в /etc/systemd/journald.conf:
[Journal]
SystemMaxUse=500M
Compress=yes
После правки конфигурации службу журнала перезапускают, а немедленную уборку выполняют через journalctl --vacuum-size=500M либо journalctl --vacuum-time=30d. Ротация классических лог-файлов живёт в logrotate. Проверить конфигурацию без выполнения изменений можно в режиме отладки:
logrotate -d /etc/logrotate.conf
Состояние ротации хранится в файле /var/lib/logrotate/status: по нему видно, когда обработчик заходил в последний раз и что крутил. Если в /var/log/nginx лежат только свежие файлы без суффиксов .1 и .gz, ротация для сайта не настроена, и место съедается медленно, без единого оповещения от мониторинга. Для собственного приложения с журналом в /var/log/app настройка занимает один блок:
/var/log/app/app.log {
weekly
rotate 8
compress
delaycompress
missingok
notifempty
postrotate
systemctl reload app.service
endscript
}
Здесь еженедельный поворот, хранение восьми копий, сжатие со сдвигом на один шаг и мягкая перезагрузка службы после ротации.
Временные файлы чистит механизм tmpfiles: настройка лежит в /etc/tmpfiles.d, уборку по расписанию выполняет systemd-tmpfiles --clean. Забытые файлы старше месяца в /var/tmp ищут так:
find /var/tmp -type f -mtime +30
Кэш пакетов убирают через apt-get clean или dnf clean all, старые ядра на Debian и Ubuntu снимает apt-get autoremove --purge, в семействе RHEL количество хранимых ядер ограничивает параметр installonly_limit в /etc/dnf/dnf.conf. Отдельная строка бюджета - контейнеры:
docker system df
docker system prune --filter "until=168h"
Вторая команда убирает остановленные контейнеры, потерянные образы и кэш сборки старше недели; тома она по умолчанию не трогает, и это правильно: решения об удалении томов человек принимает сам.
Состояние накопителей, температуры и ошибки ядра за месяц
Накопители изнашиваются предсказуемо, и месячная сверка ловит тренд задолго до отказа. Базовая проверка занимает секунды:
smartctl -H /dev/sda
Ответ PASSED значит, что встроенная самодиагностика не видит проблем, но итоговое здоровье смотрят по атрибутам:
smartctl -A /dev/sda | egrep "Reallocated_Sector_Ct|Current_Pending_Sector|Temperature_Celsius|Power_On_Hours"
Reallocated_Sector_Ct и Current_Pending_Sector должны оставаться нулями. Ноль, ставший единицей, не причина для тревоги, а причина для наблюдения; рост от прогона к прогону - уже основание планировать замену диска. Раз в месяц полезно запускать короткий тест самодиагностики:
smartctl -t short /dev/sda
smartctl -l selftest /dev/sda
Первая команда запускает тест, вторая показывает историю результатов. Для NVMe те же вопросы задаёт smartctl -a /dev/nvme0: в выводе есть строки Percentage Used и Media and Data Integrity Errors, по которым видно износ и ошибки целостности.
Температуры снимают пакетом lm-sensors командой sensors, накопители отдают свою температуру в атрибутах SMART. Значение само по себе мало что говорит, смысл появляется в сравнении с прошлым месяцем: стабильные цифры при той же нагрузке - норма, заметный прирост при неизменной нагрузке - сигнал о проблемах охлаждения.
Журнал ядра за месяц просматривают на ошибки ввода-вывода и сбои памяти:
journalctl -k -p err --since "30 days ago"
dmesg -T --level=err,warn
Ищут сообщения с "I/O error", ошибки файловой системы EXT4-fs, записи о сбросах nvme-устройств. Исправляемые ошибки памяти собирает служба rasdaemon, а сводку по ним выводит ras-mc-ctl --summary. Единичный сбой и устойчивый поток сбоев - разные ситуации: первый наблюдают, второй требует немедленной реакции.
Ревизия учётных записей и сроки сертификатов с ключами
Учётные записи обрастают лишним медленно: тестовый доступ "до конца недели", подрядчик с закрытым проектом, стажёр прошлого лета. Месячная ревизия отвечает на три вопроса: кто входил, у кого какие права, у кого пароль не менялся год. Начинают с тех, кто не входил давно:
lastlog -b 60
Команда выводит пользователей, чей последний вход старше шестидесяти дней. Дальше список сверяют с кадровой реальностью: уволенных блокируют, а не удаляют сразу. Сначала архивируют домашний каталог и проверяют, что архив читается, и только потом убирают учётную запись. Блокировка на время разбора:
usermod -L username
Возраст пароля смотрят через chage:
chage -l username
chage -M 90 -W 7 username
Первая команда показывает возраст и политику пароля, вторая задаёт максимум девяносто дней и предупреждение за неделю до истечения. Административные доступы проверяют шире. Список UID 0 обязан содержать только root:
awk -F: '$3 == 0 {print $1}' /etc/passwd
Файлы в /etc/sudoers.d просматривают на предмет правил с NOPASSWD и правами на всё подряд, синтаксис проверяет visudo -c. Эту проверку прогоняют после каждого изменения sudoers, а не только раз в месяц. Ключи SSH из authorized_keys ушедших коллег удаляют в тот же день, а не в конце квартала.
С сертификатами главная беда не в самом сертификате, а в дате. Сроки смотрят так:
openssl x509 -in cert.pem -noout -dates
openssl x509 -checkend 2592000 -noout -in cert.pem
Первая команда печатает начало и конец срока, вторая завершается успешно, пока сертификат проживёт больше тридцати дней. Если перевыпуск ручной, дата попадает в календарь с запасом. Автоматическое обновление через certbot тоже проверяют: certbot certificates покажет все известные ему сертификаты, certbot renew --dry-run прогонит обновление без изменения файлов, а перезагрузку службы после реального перевыпуска выполняет deploy-hook с командой вида systemctl reload nginx. Вдобавок смотрят права на секреты приложений: файлы .env не должны быть читаемы всеми:
find /srv -name ".env" -perm /077
Пустой вывод - то, что хочется увидеть.
Поведение служб, слушающие порты и синхронизация времени
Службы оставляют следы за месяц, и следы читаются быстрее инцидентов. Отправная точка:
systemctl --failed
Для каждого упавшего юнита смотрят журнал за месяц и решают, было ли падение разовым сбоем или закономерностью. Число автоматических перезапусков systemd считает сам:
systemctl show nginx.service -p NRestarts
Свойство NRestarts растёт у служб с параметром Restart=on-failure: служба падает ночью, поднимается за секунду, мониторинг молчит, потому что проверка прошла уже после подъёма. Ненулевое значение за месяц - причина открыть журнал и найти корень. Ошибки по всей системе собирает journalctl -p err --since "30 days ago".
Лишние службы убирают из автозапуска:
systemctl disable --now имя-службы
systemctl mask имя-службы
Первая команда останавливает службу и исключает её из автозапуска, вторая запрещает запуск даже при зависимости от других юнитов. Каждое такое решение записывают в протокол: через полгода обязательно спросят, почему службы нет.
Сеть проверяют с двух концов: что слушает сервер и что разрешено фильтром. Слушающие сокеты:
ss -tulpn
Вывод сверяют с известным списком: лишний порт означает либо новую службу, о которой никто не сообщил, либо чужой процесс. Удобно держать снимок и сравнивать:
ss -tulpn > /root/ports.txt
diff /root/ports.old.txt /root/ports.txt
Правила фильтрации смотрят по инструменту: nft list ruleset показывает полный набор nftables, firewall-cmd --list-all выводит зоны firewalld, ufw status verbose перечисляет правила ufw. В правилах ищут забытые временные разрешения: порт, открытый "на вечер" для теста, живёт годами.
Время проверяют через timedatectl: в выводе должны стоять NTP service: active и System clock synchronized: yes. Подробности для chrony дают chronyc tracking и chronyc sources: первая команда показывает смещение часов, вторая список серверов времени с их качеством. Смысл не в церемонии: рассинхронизация ломает TLS-соединения, смешивает журналы разных серверов при разборе инцидента и сдвигает задания cron. Пять минут проверки экономят часы разбора.
Протокол изменений и границы чек-листа рядом с мониторингом
Последний пункт цикла держит всё вместе. Прогон ставят в календарь фиксированным блоком, один рабочий день в месяц, без варианта "когда появится время": чек-лист, который выполняется по остаточному принципу, через квартал превращается в формальность. Протокол выполнения - обычный текстовый файл или задача в системе учёта, по одной записи на прогон: дата, исполнитель, версия чек-листа, результат по каждому пункту, найденные отклонения, задачи-последствия. Выглядит скромно:
дата | исполнитель | версия | пункт | результат | что сделано | задача
Ценность проявляется позже. Через квартал записи отвечают на вопросы, которые иначе повисают в воздухе: когда начался рост занятости места, после какого обновления служба стала падать по ночам, кто и почему открыл порт. Протокол превращает обслуживание из последовательности галочек в историю сервера, у которой можно перечитать предыдущие главы.
Чек-лист при этом остаётся живым документом. Раз в квартал его пересматривают: новые сервисы добавляют пунктами, исчезнувшие убирают вместе с их проверками. Когда по метрике настроено автоматическое оповещение, ручная проверка уходит из списка: следить за свободным местом каждую минуту должен мониторинг, а не человек раз в месяц. Пара Prometheus с Alertmanager, Zabbix или Netdata закрывает события: место кончилось, служба остановилась, сертификат истекает. Чек-лист отвечает за другое: за то, что осмотрено глазами и руками. Тест восстановления оповещение не сделает, тренд переназначенных секторов не покажет, забытый временный доступ в sudoers не найдёт. Разделение простое: мониторинг ловит события, месячный цикл ловит дрейф.
Пункты цикла делят по уровню ответственности. Инвентаризацию портов и просмотр журналов можно доверить начинающему администратору, тест восстановления и ревизию правил фильтрации оставляют за старшим. Протокол делает передачу безопасной: новый человек читает последние записи и понимает состояние сервера без устных пересказов.
Плата за месячную дисциплину небольшая, несколько часов работы. Взамен сервер большую часть года живёт в известном состоянии, деградация замечается на стадии, когда её исправляют планово, а перед разбором любого сбоя есть протокол, из которого видно, что менялось в последний месяц. Чек-лист работает как страховка: не та, что предотвращает событие, а та, что превращает неизвестное в известное. А известное чинить всегда дешевле.