Что можно выключить, а что держит бизнес: ревизия сервисов на чужом сервере
У вас на руках карта: таблица процессов, портов, сайтов и баз, собранная за вечер разведки по чужому серверу. Теперь встаёт вопрос сложнее — что из этого можно спокойно выключить, а что окажется тем самым скриптом без комментариев, который держит выставление счетов или прием платежей. Интуиция здесь работает плохо: «выглядит заброшенным» и «действительно не нужно» — разные вещи, а цена ошибки в обе стороны реальная — либо вы тащите балласт годами, либо роняете процесс, который был не виден с вашего угла зрения. Ниже — рабочая методология принятия решения, а не гадание по внешнему виду процесса.
Содержание
- Карта — это список кандидатов, а не список приговорённых
- Логи обращений: считаем не за неделю, а за реальный цикл
- Сетевой трафик: смотрим то, что логи не пишут
- Разговор с бизнесом: то, чего нет ни в логах, ни в трафике
- Как отключать: поэтапно и с возможностью отката
- Таблица решений: фиксируем вывод по каждой строке карты
Карта — это список кандидатов, а не список приговорённых
Если вы уже прошли шаг инвентаризации и собрали таблицу «что — порт — домен — чем управляется — уверенность» из статьи «Как понять, что вообще крутится на чужом сервере: карта за вечер», у вас на руках список всего, что есть. Это отправная точка, а не готовое решение. Карта отвечает на вопрос «что существует», а эта статья — на вопрос «что из этого можно тронуть».
Разница принципиальна. Строка «редис, кеш сессий, предполагаю» ничего не говорит о том, можно ли его выключить — только о том, что редис есть и, вероятно, для чего-то нужен. Строка «скрипт sync.sh, cron каждые 15 минут, не знаю зачем» — не находка «мусор», а открытый вопрос. Смешивать инвентаризацию и решение об отключении — частая ошибка: увидев незнакомый процесс, сразу тянутся к systemctl stop, вместо того чтобы сначала собрать доказательства.
Дальше — три независимых источника доказательств, которые стоит проверить прежде чем принимать решение по каждой строке карты: логи обращений, живой сетевой трафик и разговор с людьми, которые могут знать про процесс то, что не видно ни в одном логе.
Логи обращений: считаем не за неделю, а за реальный цикл
Первый и самый доступный источник — логи. Но здесь легко попасть в ловушку короткого окна наблюдения: если смотреть логи за последние семь дней, любой сервис с периодом обращения раз в месяц или раз в квартал покажется мёртвым.
Для веб-сервисов начните с access-логов nginx или Apache, отфильтрованных по конкретному домену или location:
# сколько обращений к домену за последние 30 дней, по дням
awk -v d1="$(date -d '30 days ago' '+%d/%b/%Y')" '$4 ~ d1 {print}' /var/log/nginx/access.log | wc -l
# то же самое проще через grep по логам с ротацией (zgrep для .gz)
zgrep -h "example-old-service.ru" /var/log/nginx/access.log* | awk '{print $4}' | cut -d: -f1 | sort | uniq -c
Смотрите не только на количество запросов, но и на то, кто их шлёт: реальный трафик с разных IP и User-Agent — это одно, а один и тот же внутренний IP, который раз в час ходит на /health, — совсем другое; это health-check мониторинга, и его исчезновение при отключении заметит не пользователь, а система алертинга.
Для процессов, у которых нет веб-логов, источник — systemd journal и логи самого приложения:
journalctl -u имя-сервиса --since "90 days ago" | wc -l
journalctl -u имя-сервиса --since "90 days ago" | tail -50
Для баз данных проверьте не факт подключения (соединение может держаться открытым месяцами без единого запроса), а реальные запросы. В MySQL/MariaDB включите на время наблюдения general log или slow log с низким порогом, в PostgreSQL — log_statement = 'all' временно на тестовом окне, не постоянно (это заметно нагружает диск логами). Важно зафиксировать дату последней реальной записи или изменения в таблице:
-- MySQL: когда последний раз менялась таблица
SELECT table_name, update_time FROM information_schema.tables WHERE table_schema = 'имя_базы';
Если update_time — год назад, а к базе всё ещё кто-то подключается раз в день, это похоже на процесс, который читает старые данные, но ничего не пишет: возможно, архив для отчётности, который трогать нельзя, хотя выглядит неактивным. Классический пример — сервис, который раз в месяц собирает данные для закрытия периода: 28 дней он молчит, а на 29-й кто-то заходит по прямой ссылке. Подробнее о том, как отличить «правда не нужен» от «просто редко используется», — в статье «Как убедиться, что сервис правда никому не нужен, прежде чем его гасить».
Минимальный ориентир по окну наблюдения: неделя ловит только ежедневные и еженедельные обращения, месяц — ежемесячные (закрытие периода, биллинг), квартал — сезонные и ежеквартальные отчёты. Если бизнес хоть немного сезонный (розница, туризм, сельское хозяйство), закладывайте окно минимум в квартал перед тем как считать сервис мёртвым по логам.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверСетевой трафик: смотрим то, что логи не пишут
Логи фиксируют только то, что приложение решило записать — а решает об этом сам код, который вы, возможно, не читали и не понимаете. Сетевой трафик честнее: он показывает факт соединения независимо от того, логирует его приложение или нет.
Простейший способ — счётчики iptables на конкретный порт, если вы уже используете firewall с правилами по портам:
iptables -L -v -n --line-numbers | grep :3306
Столбцы pkts и bytes растут с каждым проходящим пакетом — если счётчик не двигается несколько дней подряд при повторных проверках, это сильный сигнал, что порт снаружи никто не трогает. Если правил под конкретный порт ещё нет, живое наблюдение проще сделать через tcpdump на короткое время (не оставляйте его работать сутками — быстро съедает диск):
tcpdump -i any port 3306 -nn -c 50
Для сервисов с явным TCP-состоянием полезно посчитать количество установленных соединений во времени — не разово, а как метрику, которую вы снимаете несколько раз в день на протяжении недели-двух:
ss -tn state established '( dport = :3306 or sport = :3306 )' | wc -l
Оберните это в простой cron, который раз в час пишет число в файл — через неделю у вас будет график без мониторинга, только wc -l и текстовый файл. Для веб-сервисов на nginx включите stub_status — там сразу видно число активных соединений без парсинга логов.
Отдельно проверьте исходящий трафик — это направление часто упускают. Сервис может не принимать входящих запросов (значит выглядит мёртвым по входящим портам), но при этом сам куда-то стучится: отправляет вебхуки, синхронизирует данные с внешним API, шлёт email через SMTP-relay. Отключить его — значит оборвать не входящий, а исходящий процесс, который снаружи никак не виден по ss -tulpn.
# исходящие соединения от конкретного процесса по PID
lsof -p PID -i
Если после недели-двух наблюдения трафик в обе стороны нулевой — это уже не догадка, а измеренный факт, на который можно опираться при принятии решения.
Разговор с бизнесом: то, чего нет ни в логах, ни в трафике
Технические доказательства покрывают не всё. Есть класс зависимостей, которые не оставляют следа ни в логах, ни в сетевом трафике: резервный путь отказоустойчивости, который по определению молчит, пока всё хорошо; интеграция, которую партнёр запускает вручную раз в год перед конкретным событием; лицензионный демон, который проверяется не по сети, а локальным файлом; процесс, который держит открытым порт просто потому что его боятся трогать, хотя формально он мёртв.
Прежде чем гасить что-то с неочевидным назначением, пройдитесь по трём вопросам с людьми, которые могут знать ответ:
- Финансы и бухгалтерия. Спросите напрямую: есть ли процессы закрытия месяца, сверки с банком, экспорта для налоговой, завязанные на этот сервер. Ответ «не знаю, спросите у ИТ» — тоже результат: скорее всего, сервис не используется этой стороной, но стоит уточнить у предыдущего ответственного, если он ещё доступен.
- Продажи и поддержка клиентов. Некоторые интеграции обслуживают не сотрудников, а внешних партнёров напрямую — прежний API, старый вебхук, форма на лендинге, который формально не продвигается, но получает трафик по прямым ссылкам из старой рекламы. Отдел продаж часто знает о таких хвостах то, чего нет в документации.
- Юридическая и договорная сторона. Если сервер достался вместе с бизнесом (покупка компании, смена подрядчика), уточните, нет ли действующих договорных обязательств перед партнёрами, привязанных к конкретному сервису — их отключение может быть не техническим, а юридическим вопросом.
Формулируйте вопрос бизнес-стороне не техническим языком («что делает процесс xyz.py»), а языком процессов: «есть ли у нас процесс отправки данных в налоговую раз в месяц», «использует ли кто-то внешний старый личный кабинет для партнёров». Люди, далёкие от инфраструктуры, не смогут ответить на вопрос про имя процесса, но обычно точно знают, какие бизнес-процессы у них есть.
Если публичный API сервиса продолжает получать обращения от внешних интеграций, а не только от внутренних процессов, отключение требует отдельного, более деликатного плана — как минимум предупреждения через сам API перед полной остановкой. Этот случай подробно разобран в статье «Сервис закрыт, а его API кто-то продолжает дёргать: как отключать по-человечески».
Как отключать: поэтапно и с возможностью отката
Даже если все три источника — логи, трафик, разговор с бизнесом — говорят «не нужен», не отключайте сразу и необратимо. Правильный порядок снижает цену ошибки почти до нуля.
Шаг 1. Мягкая блокировка вместо остановки. Для веб-сервиса замените реальный контент ответом 503 Service Unavailable с логированием каждого такого ответа отдельно от обычных логов, вместо того чтобы полностью гасить nginx location или процесс:
location /старый-сервис/ {
access_log /var/log/nginx/deprecated-service-hits.log;
return 503 "Сервис отключён, обратитесь в поддержку";
}
Это даёт неделю-две наблюдения: если файл deprecated-service-hits.log пустой — предположение подтвердилось, если растёт — вы поймали живой трафик до того, как что-то реально сломалось.
Шаг 2. Ограничение доступа вместо удаления. Для процессов без веб-интерфейса — сначала закройте порт файрволом только для известных, доверенных источников (внутренняя сеть, мониторинг), оставив сам процесс работающим:
iptables -A INPUT -p tcp --dport 3306 -s 10.0.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP
Если что-то важное перестало работать — это будет заметно быстрее, чем при полной остановке процесса, а откатить правило файрвола — секундное дело, в отличие от восстановления упавшего сервиса.
Шаг 3. Остановка с сохранением состояния. Только после периода наблюдения без инцидентов — реальная остановка, но без удаления:
systemctl stop имя-сервиса
systemctl disable имя-сервиса
# Docker: контейнер остановлен, но образ и volume не тронуты
docker stop имя-контейнера
Не удаляйте юнит, образ, volume или базу данных на этом шаге. Держите ещё один период наблюдения — от двух недель до месяца, в зависимости от того, насколько редкий цикл обращений вы предполагаете у этого сервиса, — прежде чем переходить к финальной очистке.
Шаг 4. Бэкап перед окончательным удалением. Только когда вы уверены, что сервис не всплывёт, снимите полный снапшот перед физическим удалением: дамп базы, архив каталога приложения, экспорт конфигурации:
mysqldump --single-transaction имя_базы > /backup/имя_базы_перед_удалением_$(date +%F).sql
tar czf /backup/приложение_$(date +%F).tar.gz /opt/приложение/
Храните такой бэкап минимум несколько месяцев отдельно от самого сервера — именно на случай, что кто-то через полгода вспомнит про данные, которые казались ненужными. Полный порядок финального вывода сервиса из эксплуатации — не только сам процесс, но и связанные домены, платные интеграции, записи DNS — подробно расписан в статье «Вывод сервиса из эксплуатации: чтобы через год он не всплыл в счёте».
Таблица решений: фиксируем вывод по каждой строке карты
Результат всей работы — не ощущение «вроде разобрались», а конкретная таблица, которая ложится поверх карты из вечерней инвентаризации. На каждую строку карты добавьте четыре колонки:
| Сервис | Доказательства (логи/трафик) | Ответ бизнеса | Решение |
|---|---|---|---|
| редис (кеш сессий) | активные обращения ежедневно | — (техническая часть, бизнес не в курсе) | держим |
| скрипт sync.sh | обращения к внешнему API каждые 15 минут, ответ 200 | продажи подтвердили: синхронизация с партнёрским каталогом | держим, но задокументировать |
| старый личный кабинет партнёров | 0 обращений за 60 дней, 503 не дал новых хитов за 2 недели | юротдел: договор с последним партнёром закрыт год назад | выводим из эксплуатации |
| демон license-checker | нет сетевого трафика, лог активности раз в квартал | ИТ: проверка лицензии стороннего ПО | держим |
Колонка «решение» должна быть одной из трёх: «держим», «выводим из эксплуатации» (с датой начала поэтапного отключения), «нужно больше данных» — третий вариант совершенно нормален и не означает провал ревизии, это просто честная фиксация того, что решение пока преждевременно.
Эту таблицу стоит хранить рядом с картой сервисов как живой документ, а не разовый отчёт — при следующей передаче сервера новому человеку она сэкономит те же часы разведки, которые вы потратили сами.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько времени в среднем занимает вся ревизия — от карты до финального решения по каждому сервису?
Зависит от числа спорных строк в карте. Если из двадцати найденных процессов пятнадцать понятны сразу (веб-сервер, основная база, основное приложение), а спорных пять — реалистичный срок с учётом периода наблюдения по каждому это две-четыре недели, из которых собственно ваше активное время — несколько часов на настройку логирования и разговоры с бизнесом.
Что делать, если бизнес-сторона не может дать внятный ответ, а сервис явно кому-то нужен по трафику?
Доверяйте измеримым данным больше, чем отсутствию ответа. Если трафик реальный и регулярный, а никто не берёт на себя ответственность за процесс — это сам по себе управленческий сигнал (владелец процесса уволился или сменил роль), но технически сервис остаётся в статусе «держим» до выяснения, независимо от того, нашёлся ли формальный владелец.
Можно ли пропустить этап мягкой блокировки и сразу останавливать сервис, если уверенность высокая?
Технически можно, но смысл поэтапного подхода именно в цене ошибки при высокой уверенности, которая всё равно не стопроцентная. Runtime-блокировка с логированием стоит пять минут настройки и снимает риск полностью — пропускать её имеет смысл только для откровенно тестовых артефактов без единого шанса на реальное использование.
Как быть с сервисами, у которых нет логов вообще и трафик не измерить (например, локальный cron-скрипт без сети)?
Здесь единственный источник — сам код и разговор с людьми. Прочитайте, что скрипт делает: если он пишет в файл или таблицу — проверьте дату последней записи; если меняет состояние системы (ротация, очистка, бэкап) — оцените, что сломается при остановке ротации логов или бэкапов, и это часто перевешивает отсутствие сетевых доказательств.
Нужно ли согласовывать отключение письменно, если решение подтверждено логами, трафиком и разговором с бизнесом?
Да, хотя бы коротким письмом или тикетом с перечислением проверок и датой. Это не бюрократия ради галочки, а защита себя: если через полгода кто-то спросит «кто и почему выключил X», у вас будет не «показалось, что не нужно», а конкретная методология и зафиксированный ответ ответственного за процесс человека.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →