Как читать и анализировать логи Minecraft сервера

Как читать и анализировать логи Minecraft сервера

Сервер упал ночью. Игроки пишут что "все лагало, потом выбросило". Вы заходите утром, сервер работает - его перезапустил watchdog. Что произошло? Без логов вы никогда не узнаете.

Логи - единственный достоверный источник информации о том, что происходит на сервере. Не "мне кажется", не "наверное плагин глючит", а конкретные записи с точным временем, уровнем критичности и описанием проблемы. Если вы администрируете Minecraft сервер и не умеете читать логи - вы работаете вслепую.

В этой статье разберем все: где лежат логи, как устроен формат записей, что означают уровни, как находить типичные проблемы и как автоматизировать анализ.

Где хранятся логи

latest.log

Основной файл - logs/latest.log в корне сервера. Сюда пишется все, что происходит с момента последнего запуска. При каждом перезапуске сервера предыдущий latest.log архивируется.

server/
├── logs/
│   ├── latest.log              <-- текущая сессия
│   ├── 2026-03-25-1.log.gz     <-- вчерашний лог (сжатый)
│   ├── 2026-03-24-1.log.gz
│   ├── 2026-03-24-2.log.gz     <-- если сервер перезапускался дважды
│   └── ...
├── crash-reports/
│   └── crash-2026-03-25-server.txt
└── ...

Архивы хранятся в формате gzip. Чтобы прочитать старый лог:

# Просмотр сжатого лога
zcat logs/2026-03-25-1.log.gz | less

# Поиск по сжатому логу
zgrep "ERROR" logs/2026-03-25-1.log.gz

crash-reports/

Когда сервер падает с фатальной ошибкой, он создает файл в папке crash-reports/. Это не то же самое, что обычный лог - краш-репорт содержит детальный снимок состояния сервера на момент падения: стектрейс, загруженные плагины, информацию о системе, состояние памяти.

Имя файла включает дату и время: crash-2026-03-25-151432-server.txt.

debug/

На Paper серверах есть папка debug/ - туда попадают thread dump'ы и другая диагностическая информация. Про них подробнее ниже.

Формат лог-записи

Каждая строка в логе имеет стандартный формат:

[15:42:01] [Server thread/INFO]: Player_Steve joined the game
[15:42:15] [Server thread/WARN]: Can't keep up! Is the server overloaded?
[15:43:02] [Server thread/ERROR]: Could not pass event PlayerMoveEvent

Разберем по частям:

  • [15:42:01] - время события (HH:MM:SS)
  • [Server thread/INFO] - поток (thread) и уровень логирования
  • Текст после : - само сообщение

Поток важен. Server thread - это главный тик-поток, на котором работает вся игровая логика. Если ошибка происходит в Async Chat Thread или Netty Epoll Server IO - это другая история, и причины другие.

Уровни логирования

INFO

Обычные информационные сообщения. Подключение игроков, загрузка плагинов, сохранение мира. Это 95% вашего лога.

[15:42:01] [Server thread/INFO]: Starting minecraft server version 1.20.4
[15:42:03] [Server thread/INFO]: Loading properties
[15:42:05] [Server thread/INFO]: Done (4.832s)! For help, type "help"

INFO-сообщения обычно можно игнорировать при поиске проблем. Но иногда полезная информация скрыта именно тут - например, время загрузки плагинов может показать, какой из них тормозит запуск.

WARN

Предупреждения. Сервер столкнулся с чем-то нежелательным, но продолжает работать.

[15:42:15] [Server thread/WARN]: Can't keep up! Is the server overloaded?
    Running 5023ms or 100 ticks behind

Это самое знаменитое предупреждение Minecraft. Означает, что сервер не успевает обрабатывать тики вовремя. Если появляется изредка - не страшно. Если каждые несколько секунд - у вас серьезные проблемы с производительностью.

Другие частые WARN:

[WARN]: Ambiguity between arguments [...]  -- неоднозначность команд, безобидно
[WARN]: UUID of player X is ...             -- проблемы с UUID, часто при offline-mode
[WARN]: Connection throttled: 192.168.1.50  -- слишком частые подключения с одного IP

ERROR

Ошибки. Что-то сломалось. Плагин упал, не удалось загрузить мир, ошибка в конфигурации.

[15:43:02] [Server thread/ERROR]: Could not pass event PlayerMoveEvent to ExamplePlugin v1.0
org.bukkit.event.EventException: null
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310)
    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70)
    ...
Caused by: java.lang.NullPointerException
    at com.example.plugin.MoveListener.onPlayerMove(MoveListener.java:45)

Вот это уже важно. ERROR всегда требует внимания. После ERROR обычно идет стектрейс - цепочка вызовов, которая привела к ошибке. Как его читать - разберем ниже.

FATAL

Критическая ошибка, после которой сервер обычно останавливается. Встречается редко, но если видите FATAL - это серьезно.

[15:45:01] [Server thread/FATAL]: Encountered an unexpected exception
java.lang.OutOfMemoryError: Java heap space

Нехватка памяти, повреждение данных мира, баг в ядре сервера - все это может вызвать FATAL.

Как читать стектрейсы

Стектрейс (stack trace) - цепочка вызовов методов, которая привела к ошибке. Читать его нужно сверху вниз, но искать причину - снизу вверх.

[ERROR]: Could not pass event PlayerInteractEvent to ShopPlugin v2.1
org.bukkit.event.EventException: null
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:310)
    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:70)
    at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:545)
    at org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(CraftEventFactory.java:540)
    at net.minecraft.server.level.ServerPlayerGameMode.useItemOn(ServerPlayerGameMode.java:532)
Caused by: java.lang.NullPointerException: Cannot invoke "org.bukkit.inventory.ItemStack.getType()" because "item" is null
    at com.example.shop.ShopListener.onInteract(ShopListener.java:78)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

Алгоритм чтения:

  1. Первая строка - что произошло: "Could not pass event PlayerInteractEvent to ShopPlugin". Сразу понятно - проблема в ShopPlugin при обработке клика игрока.

  2. "Caused by" - реальная причина. NullPointerException: Cannot invoke "getType()" because "item" is null. Плагин пытается получить тип предмета, но предмет равен null.

  3. Строка с вашим плагином - ShopListener.java:78. Это строка 78 в файле ShopListener.java. Если плагин ваш - идете чинить эту строку. Если чужой - создаете issue на GitHub или ищете обновление.

Строки из org.bukkit, net.minecraft, java.lang и sun.reflect - это внутренности сервера и Java. Они обычно не являются причиной проблемы, а лишь показывают путь выполнения.

Типичные ошибки и что с ними делать

"Can't keep up! Is the server overloaded?"

Уже упоминал выше. Сервер отстает от нормальных 20 тиков в секунду. Причины:

  • Слишком много сущностей
  • Тяжелый плагин в главном потоке
  • Недостаточно RAM и частые GC-паузы
  • Медленный диск (SSD обязателен для серверов)

Подробно про диагностику лагов читайте в нашем гайде по причинам лагов.

"Connection throttled"

[WARN]: Connection throttled: 185.220.101.34

Кто-то подключается слишком часто. Может быть бот, может быть DDoS-атака на уровне приложения. Если видите один IP с сотнями throttle - блокируйте его через файрвол.

"Disconnect: Outdated client/server"

[INFO]: Disconnect: com.mojang.authlib.GameProfile@... (Outdated client! Please use 1.20.4)

Игрок пытается зайти с неправильной версией. Если таких записей много с одного IP - это может быть сканер, который перебирает версии протокола.

OutOfMemoryError

[FATAL]: java.lang.OutOfMemoryError: Java heap space

Закончилась память. Проверяйте флаги запуска - сколько памяти выделено серверу через -Xmx. Используйте правильные JVM-флаги. Также может быть утечка памяти в плагине - плагин создает объекты и не освобождает их.

"IOException: Connection reset by peer"

[WARN]: IOException: Connection reset by peer

Клиент разорвал соединение. Обычно безобидно - игрок вылетел или закрыл игру. Но если массово - может быть атака. Посмотрите, с каких IP приходят эти разрывы.

"Moved too quickly!"

[WARN]: Player_Steve moved too quickly! (23.45, 0.0, 18.76)

Игрок переместился слишком быстро. Либо лаг, либо читер использует speed-хак. Единичные случаи - нормально (лаги). Если один игрок стабильно получает такие предупреждения - стоит проверить.

Краш-репорты

Краш-репорты более информативны, чем обычные логи. Откройте файл из crash-reports/ - он структурирован по разделам:

---- Minecraft Crash Report ----

Time: 2026-03-25 15:14:32
Description: Exception in server tick loop

java.lang.OutOfMemoryError: Java heap space
    at net.minecraft.nbt.CompoundTag.copy(CompoundTag.java:265)
    ...

-- System Details --
Minecraft Version: 1.20.4
Operating System: Linux (amd64) version 5.15.0
Java Version: 17.0.9
Memory: 234217728 bytes / 8589934592 bytes
Plugins:
  EssentialsX v2.20.1
  WorldGuard v7.0.9
  ShopPlugin v2.1
  ...

-- World Details --
Loaded chunks: 4521
Entities: 18432

На что обращать внимание:

  1. Description - краткое описание причины падения
  2. Стектрейс - где именно произошла ошибка
  3. Memory - сколько памяти было использовано vs доступно. Если использовано близко к максимуму - OOM
  4. Entities - если число огромное (10000+), возможно причина именно в этом
  5. Plugins - список загруженных плагинов. Если в стектрейсе упоминается один из них - это главный подозреваемый

Thread dump'ы

Thread dump - снимок всех потоков сервера в конкретный момент. Полезно, когда сервер "завис" - не падает, но и не отвечает.

На Paper серверах:

/paper dump threads

Или через kill-сигнал:

kill -3 $(cat server.pid)
# или
jstack $(cat server.pid) > thread_dump.txt

В thread dump ищите потоки в состоянии BLOCKED или WAITING. Если Server thread заблокирован - сервер висит. Смотрите, на каком вызове он завис:

"Server thread" #1 prio=5 os_prio=0 tid=0x00007f... nid=0x1a23 waiting for monitor entry
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.example.plugin.Database.query(Database.java:156)
    - waiting to lock <0x000000076ab8c120>
    at com.example.plugin.Handler.onEvent(Handler.java:42)

Здесь видно, что главный поток заблокирован на запросе к БД в каком-то плагине. Плагин делает синхронный запрос к базе данных в главном потоке - классическая ошибка, которая вешает весь сервер.

Поиск следов взлома в логах

Логи - ваша система безопасности. Если кто-то пытается взломать сервер, следы остаются. Вот что искать:

Подозрительные команды

grep -i "issued server command" logs/latest.log | grep -i "op\|deop\|ban\|perm\|gamemode\|give"

Ищем, кто выполнял административные команды. Если игрок, который не должен быть оператором, вдруг выполняет /op или /gamemode - это взлом.

Попытки эксплойтов

# Поиск подозрительно длинных сообщений (возможный book exploit)
grep "AsyncChat" logs/latest.log | awk '{if(length($0) > 500) print}'

# Поиск попыток использования серверных команд через чат
grep -i "selector\|@a\|@e\|@r\|@p" logs/latest.log

Массовые подключения

# Кто подключался чаще всего
grep "logged in with entity" logs/latest.log | awk -F'[/:]' '{print $2}' | sort | uniq -c | sort -rn | head 20

Если один ник или IP заходит сотни раз - это бот или атака. Стоит настроить защиту от ботов.

Необычная активность ночью

# Что происходило между 3:00 и 5:00
grep "^\[0[3-4]:" logs/latest.log | grep -v "INFO.*save\|INFO.*Saving"

Если ночью, когда никто не играет, происходит что-то необычное - стоит разобраться.

Подробнее про безопасность: чеклист безопасности Minecraft сервера и мониторинг атак.

Полезные grep-команды

Grep - ваш лучший друг при анализе логов. Вот набор команд, которые я использую постоянно:

# Все ошибки за последнюю сессию
grep "ERROR\|FATAL" logs/latest.log

# Ошибки конкретного плагина
grep "PluginName" logs/latest.log | grep -i "error\|exception\|warn"

# Сколько раз каждый уровень встречается
grep -c "INFO\]" logs/latest.log
grep -c "WARN\]" logs/latest.log
grep -c "ERROR\]" logs/latest.log

# Кто заходил на сервер
grep "joined the game\|left the game" logs/latest.log

# Все команды, которые выполняли игроки
grep "issued server command" logs/latest.log

# Ошибки в архивных логах
zgrep "ERROR" logs/2026-03-*.log.gz

# Последние 50 ошибок с контекстом (3 строки до и после)
grep -n "ERROR" logs/latest.log | tail -50
grep -B3 -A3 "ERROR" logs/latest.log | tail -100

# Поиск по нескольким файлам одновременно
zgrep -l "OutOfMemoryError" logs/*.log.gz

Мониторинг в реальном времени

# Следить за логом в реальном времени
tail -f logs/latest.log

# Только ошибки в реальном времени
tail -f logs/latest.log | grep --line-buffered "ERROR\|WARN\|FATAL"

# С подсветкой (если есть ccze)
tail -f logs/latest.log | ccze -A

Timings и spark-отчеты

Для анализа производительности одних логов мало. Timings (устаревший) и spark (современный) дают детальную картину того, что сервер делает каждый тик.

spark-отчет показывает:

  • Какие плагины сколько времени занимают
  • Где именно тратятся ресурсы CPU
  • Состояние памяти и GC-паузы
  • Конкретные методы, которые тормозят
/spark profiler start
# подождите 3-5 минут
/spark profiler stop

spark создаст ссылку на веб-отчет. Откройте и ищите самые "тяжелые" ветки. Подробнее про профилирование - в статье про диагностику лагов.

Ротация и хранение логов

По умолчанию Minecraft хранит все архивные логи вечно. На долго живущем сервере это гигабайты. Настройте ротацию:

# Скрипт удаления старых логов (старше 30 дней)
find /path/to/server/logs -name "*.log.gz" -mtime +30 -delete

Добавьте в cron:

0 4 * * 0 find /path/to/server/logs -name "*.log.gz" -mtime +30 -delete

Но не удаляйте логи слишком рано - они могут понадобиться для расследования инцидентов. 30 дней - разумный минимум. Если место позволяет - храните 90 дней.

Автоматизация анализа

Вместо ручного парсинга каждый день можно написать простой скрипт:

#!/bin/bash
LOG="logs/latest.log"

echo "=== Server Log Summary ==="
echo "Errors:   $(grep -c 'ERROR\]' $LOG)"
echo "Warnings: $(grep -c 'WARN\]' $LOG)"
echo "Fatals:   $(grep -c 'FATAL\]' $LOG)"
echo ""
echo "=== Top Errors ==="
grep 'ERROR\]' $LOG | sed 's/\[.*ERROR\]: //' | sort | uniq -c | sort -rn | head -10
echo ""
echo "=== Player Activity ==="
echo "Joins:  $(grep -c 'joined the game' $LOG)"
echo "Leaves: $(grep -c 'left the game' $LOG)"
echo ""
echo "=== Overload Warnings ==="
grep -c "Can't keep up" $LOG

Запускайте утром - за минуту увидите картину за ночь.

Для более серьезного мониторинга используйте специализированные инструменты. О том, как настроить полноценный мониторинг, читайте в нашей статье про мониторинг Minecraft сервера.

Итого

Логи - не просто текстовые файлы, которые жрут место на диске. Это ваша черная коробка, ваш детектив, ваш источник правды.

Минимум, который должен делать каждый администратор:

  1. Проверять логи после каждого перезапуска - посмотрите, нет ли ошибок
  2. Мониторить ERROR и FATAL - это всегда требует внимания
  3. Анализировать краш-репорты - они содержат всю информацию для диагностики
  4. Периодически проверять логи на безопасность - ищите подозрительные команды и массовые подключения
  5. Настроить ротацию - чтобы диск не переполнился
  6. Выучить базовые grep-команды - это сэкономит часы времени

Не ждите, пока игроки придут с жалобами. Читайте логи проактивно - большинство проблем оставляют следы задолго до того, как становятся критичными.


Защитите свой сервер от DDoS-атак

Бесплатная защита с настройкой за 5 минут. 1 ТБ трафика в подарок.

Попробовать бесплатно


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