Анализ логов сервера: находим проблемы и ботов

Администрирование
Анализ логов сервера: находим проблемы и ботов

Анализ логов сервера — самый честный источник информации о том, что происходит с вашим проектом: мониторинг покажет, что CPU загружен, а логи Nginx ответят, кто и чем его грузит. В журналах видно всё: всплески ошибок 5xx перед падением, боты, выкачивающие сайт, попытки найти уязвимости перебором путей, медленные запросы и реальная посещаемость без прикрас счётчиков. В этой статье разберём практический анализ логов Linux-сервера тремя инструментами — GoAccess для наглядной картины, grep и awk для точечных расследований — и покажем готовые команды, которые находят ботов и проблемы за минуты. Все примеры — для Ubuntu 24.04 LTS и стандартного combined-формата логов Nginx.

Где лежат логи и что в них записано

Основные журналы, с которыми придётся работать:

  • /var/log/nginx/access.log — каждый HTTP-запрос: IP, время, метод, URL, код ответа, размер, referer, User-Agent;
  • /var/log/nginx/error.log — ошибки веб-сервера: недоступный бэкенд, превышение лимитов, проблемы с конфигом;
  • journalctl — системный журнал systemd: события сервисов, SSH, ядра;
  • /var/log/auth.log — аутентификация: входы, sudo, неудачные попытки;
  • логи приложений — PHP-FPM (/var/log/php8.3-fpm.log), MySQL, вашего кода.

Строка access.log в combined-формате выглядит так:

203.0.113.42 - - [17/Jul/2026:14:03:11 +0300] "GET /catalog/item-15 HTTP/1.1" 502 552 "-" "Mozilla/5.0 (compatible; SomeBot/1.0)"

Для работы с awk важно помнить номера полей: $1 — IP, $7 — URL, $9 — код ответа. Это стандарт, на нём построены все команды ниже.

GoAccess: вся картина по логам за одну команду

GoAccess — консольный анализатор логов, который превращает гигабайты access.log в интерактивный отчёт: топ посетителей, запрашиваемые URL, коды ответов, User-Agent, распределение по времени. Установка из репозитория Ubuntu 24.04:

sudo apt update && sudo apt install -y goaccess

Интерактивный отчёт прямо в терминале:

goaccess /var/log/nginx/access.log --log-format=COMBINED

HTML-отчёт, который можно открыть в браузере (в том числе обновляемый в реальном времени):

# разовый отчёт
goaccess /var/log/nginx/access.log --log-format=COMBINED -o /var/www/html/report.html

# live-режим: отчёт обновляется по WebSocket
goaccess /var/log/nginx/access.log --log-format=COMBINED -o /var/www/html/report.html --real-time-html

Чтобы проанализировать логи вместе с уже ротированными архивами:

zcat /var/log/nginx/access.log.*.gz | goaccess /var/log/nginx/access.log - --log-format=COMBINED

На что смотреть в отчёте в первую очередь:

  1. Панель «HTTP Status Codes» — доля 4xx и 5xx. Больше 1–2% ошибок 5xx — повод для расследования.
  2. «Hosts» — топ IP по числу запросов. Один адрес с десятками тысяч хитов — почти наверняка бот.
  3. «Requested Files» — что запрашивают. Всплески по несуществующим путям — сканеры уязвимостей.
  4. «Browsers» / «User-Agents» — сколько трафика приходится на заявленных ботов.

GoAccess парсит логи очень быстро, но на многогигабайтных файлах скорость упирается в диск — на NVMe-накопителях (у Cheap-Host они стоят во всех тарифах) гигабайтный лог разбирается за секунды.

grep и awk: точечные расследования

GoAccess отвечает на вопрос «что происходит вообще», а grep и awk — на вопрос «что случилось конкретно здесь и сейчас». Набор команд, который стоит сохранить в закладки.

Ошибки 5xx: считаем и находим виновных

# сколько всего ответов 5xx
awk '$9 ~ /^5/' /var/log/nginx/access.log | wc -l

# какие именно коды и сколько раз
awk '$9 ~ /^5/ {print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# на каких URL возникают ошибки
awk '$9 ~ /^5/ {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# в какие минуты был всплеск (группировка по времени до минут)
awk '$9 ~ /^5/ {print substr($4, 2, 17)}' /var/log/nginx/access.log | uniq -c | sort -rn | head

Дальше — за причиной в error.log. Например, ошибки 502 почти всегда означают, что бэкенд не ответил:

grep "connect() failed\|upstream timed out\|no live upstreams" /var/log/nginx/error.log | tail -20

Если в error.log видны таймауты PHP-FPM — проблема в нехватке воркеров или медленном коде; как правильно рассчитать пул, разобрано в статье об оптимизации PHP-FPM. А если 5xx появляются только под наплывом трафика — сервер упирается в лимиты, и стоит почитать про оптимизацию Nginx под высокую нагрузку.

Топ IP: кто создаёт нагрузку

# топ-20 адресов по числу запросов
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# что именно делает подозрительный IP
grep "203.0.113.42" /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head

# сколько запросов в минуту делает этот IP
grep "203.0.113.42" /var/log/nginx/access.log | awk '{print substr($4, 2, 17)}' | uniq -c | sort -rn | head

Обычный посетитель делает десятки запросов за визит. Сотни запросов в минуту с одного IP часами — это парсер, сканер или качалка.

Вычисляем ботов

Боты бывают трёх типов: честные (поисковики), заявленные (парсеры с ботовским User-Agent) и маскирующиеся под браузер. Ищем каждый тип по-своему:

# заявленные боты по User-Agent
awk -F'"' '{print $6}' /var/log/nginx/access.log | grep -i "bot\|crawl\|spider\|scan" | sort | uniq -c | sort -rn | head -20

# сканеры уязвимостей: перебор типовых путей
grep -E "\.env|wp-login|phpmyadmin|\.git/|xmlrpc\.php" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head

# кто получает много 404 (перебор несуществующих страниц)
awk '$9 == 404 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

Честного поисковика проверяйте обратным DNS: у настоящего Googlebot PTR-запись указывает на googlebot.com или google.com:

host 66.249.66.1

Если IP представляется Googlebot, а резолвится в чужую сеть — это подделка, можно смело блокировать. Найденных вредителей отправляйте в файрвол или fail2ban — подробная настройка описана в статье о комплексной защите от брутфорса.

Системные журналы: journalctl и auth.log

Веб-логи — не единственный источник. Проблемы уровня системы ищите в journalctl:

# все ошибки системных служб за сегодня
journalctl -p err --since today

# журнал конкретного сервиса
journalctl -u nginx --since "1 hour ago"

# убийца процессов OOM: не прибивало ли ядро ваши сервисы из-за нехватки памяти
sudo dmesg -T | grep -i "out of memory\|oom"

Последняя команда — обязательная проверка при «беспричинных» падениях MySQL или PHP-FPM: если ядро прибило процесс из-за нехватки памяти, в dmesg останется запись. Частое срабатывание OOM-киллера — сигнал, что серверу пора добавить RAM (у Cheap-Host апгрейд тарифа проходит без потери данных) или настроить своп.

Попытки подбора пароля к SSH смотрите так:

# количество неудачных попыток входа за сегодня
journalctl -u ssh --since today | grep -c "Failed password"

# топ атакующих IP
journalctl -u ssh --since today | grep "Failed password" | grep -oE "from [0-9.]+" | sort | uniq -c | sort -rn | head

Регламент: как анализировать логи, чтобы не утонуть

Логи полезны только при регулярной работе с ними. Практичный минимум:

ПериодичностьЧто делатьИнструмент
При инцидентеВсплеск 5xx по минутам, причина в error.log, виновные IPawk, grep
Раз в день (автоматически)HTML-отчёт GoAccess по вчерашнему логуGoAccess + cron
Раз в неделюТоп ботов, доля 4xx/5xx, новые сканеры, проверка dmesg на OOMGoAccess, journalctl
ПостоянноАвтоблокировка перебора, контроль места под логи (df -h)fail2ban, logrotate

Автоматический ежедневный отчёт делается одной строкой в cron (запуск в 00:05 по вчерашнему ротированному логу):

5 0 * * * zcat -f /var/log/nginx/access.log.1 | goaccess - --log-format=COMBINED -o /var/www/html/report-daily.html

Не забывайте про ротацию: на посещаемом сайте access.log растёт на сотни мегабайт в сутки. В Ubuntu logrotate уже настроен для Nginx (ежедневная ротация, 14 дней хранения, сжатие) — конфиг лежит в /etc/logrotate.d/nginx. Для полной картины здоровья сервера логи стоит дополнить метриками — как собрать связку графиков и алертов, описано в статье о мониторинге с Grafana и Prometheus.

FAQ

Какие логи смотреть в первую очередь при проблемах с сайтом?

Сначала error.log Nginx — там причины ошибок 5xx. Затем access.log для картины трафика, журнал приложения (PHP-FPM, Node.js) и journalctl -p err для системных ошибок. При внезапных падениях сервисов проверьте dmesg на OOM.

Как быстро посчитать ошибки 5xx в access.log?

awk '$9 ~ /^5/' /var/log/nginx/access.log | wc -l — посчитает все ответы 500–599. Девятое поле в combined-формате — код ответа.

Как отличить полезного бота от вредного?

Полезные (Googlebot, YandexBot) честно представляются в User-Agent и подтверждаются обратным DNS. Вредные маскируются под браузер, делают сотни запросов в минуту и перебирают типовые пути вроде /wp-admin, .env, .git.

GoAccess или grep/awk — что выбрать?

И то и другое: GoAccess — для общей картины (топ IP, URL, коды, боты), grep/awk — для точечных вопросов: кто вызвал всплеск 502 в 14:03, что перебирает конкретный IP.

Как логи не переполнят диск?

Ротацией занимается logrotate — для Nginx в Ubuntu она включена по умолчанию (ежедневно, 14 архивов, сжатие). Контролируйте место командой df -h; при активном трафике и долгом хранении логов выбирайте тариф с запасом по диску.

Вывод

Анализ логов сервера сводится к трём навыкам: GoAccess даёт общую картину трафика за минуту, awk по девятому полю мгновенно находит ошибки 5xx и их источники, а grep по User-Agent и типовым путям вычисляет ботов и сканеры. Добавьте еженедельный регламент и автоматический отчёт по cron — и большинство проблем вы будете замечать раньше, чем их заметят посетители.

Если нужен сервер, где и логам, и проектам хватит места и скорости — у Cheap-Host тариф Pro за 750 ₽/мес: 12 vCPU, 16 ГБ RAM и NVMe 128 ГБ, на котором GoAccess разбирает гигабайтные журналы за секунды. KVM, безлимитный трафик, выдача за 45–60 секунд — тарифы на cheap-host.onl.

Читайте также