RE:NODE

Логи BepInEx в Valheim: как читать LogOutput.log и чинить моды

Автор Команда RE:NODE
12 мин чтения


Когда сервер Valheim с модами ведёт себя странно, ответ почти всегда лежит в BepInEx/LogOutput.log в корне сервера, и почти всегда в первой ошибке, а не в последней. Читайте в три прохода. Сначала: есть ли вообще баннер BepInEx - если нет, Doorstop не внедрил загрузчик, и пока неважно, какие моды стоят. Затем строки Loading [...] и всё, где сказано Could not load или Skipping - это ваш настоящий список плагинов, где недостающие зависимости названы прямо. И наконец первая Error после запуска, с именем мода в стеке вызовов. Если лог - стена исключений без явной первой причины, перестаньте читать и делите пополам: уберите половину плагинов, перезапустите на копии мира и снова разделите. Тридцать модов - пять раундов.

Где лежат логи#

Установка Valheim с модами пишет больше чем в одно место, и нужное зависит от того, какая сторона дала сбой.

ЛогРасположениеЧто содержит
Лог BepInEx (сервер)BepInEx/LogOutput.log в корне сервераЗагрузчик, каждый плагин и собственные сообщения Unity
Консоль сервераСтандартный вывод или файл, указанный в -logFileТе же строки в реальном времени, плюс всё, что было до запуска BepInEx
Лог BepInEx (клиент)BepInEx/LogOutput.log внутри профиля модов игрокаПлагины и ошибки клиента
Лог Unity player (клиент)%USERPROFILE%\AppData\LocalLow\IronGate\Valheim\Player.logЛог Unity для клиента игры

Два свойства LogOutput.log застают людей врасплох:

  • По умолчанию он перезаписывается при каждом запуске. Перезапуск упавшего сервера, чтобы "посмотреть, повторится ли", уничтожает свидетельства первого сбоя. Сначала скачайте или скопируйте файл. Общий довод приведён в статье логи, которые стоит хранить.
  • Он настолько подробен, насколько задан уровень в `BepInEx.cfg`. По умолчанию записываются ошибки, предупреждения, сообщения и info, чего для большинства диагностики достаточно.

Настройки логирования загрузчика находятся в BepInEx/config/BepInEx.cfg. В актуальных релизах BepInEx 5 они выглядят так:

BepInEx/config/BepInEx.cfg
[Logging.Disk]WriteUnityLog = falseAppendLog = falseEnabled = trueLogLevels = Fatal, Error, Warning, Message, Info

Если добавить Debug в LogLevels (или задать All), некоторые моды становятся гораздо разговорчивее, что помогает, когда автор просит debug-лог. Потом верните как было: debug-лог на загруженном сервере быстро растёт. AppendLog = true сохраняет прошлые запуски в том же файле вместо перезаписи, что полезно при поиске сбоя, случающегося только ночью. Имена ключей были стабильны во всём BepInEx 5, но сверяйтесь со своим файлом, а не вставляйте вслепую.

На RE:NODE консоль показывает вывод сервера в реальном времени с первой строки, а файловый менеджер открывает LogOutput.log в браузере, так что читать его можно без скачивания, но копию перед перезапуском всё равно сделайте.

Как выглядит здоровый запуск#

Нельзя заметить отклонение, не зная нормы. Чистый запуск с модами проходит прелоадер, затем chainloader, затем по строке на плагин:

BepInEx/LogOutput.log
[Message:   BepInEx] BepInEx 5.4.2202 - valheim_server[Message:   BepInEx] Preloader started[Message:   BepInEx] Preloader finished[Message:   BepInEx] Chainloader ready[Message:   BepInEx] Chainloader started[Info   :   BepInEx] 4 plugins to load[Info   :   BepInEx] Loading [Jotunn 2.20.1][Info   :   BepInEx] Loading [ServerDevcommands 1.70][Info   :   BepInEx] Loading [EpicLoot 0.10.3][Info   :   BepInEx] Loading [DiscordConnector 3.1.0][Message:   BepInEx] Chainloader startup complete

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

  • Баннер называет процесс. На сервере там valheim_server, на клиенте - valheim.
  • Число в N plugins to load должно совпадать с количеством модов, которые, по вашему мнению, установлены.
  • У каждого мода есть строка Loading с версией. Если строки нет, мод не загрузился.
  • Появляется Chainloader startup complete. После неё продолжается собственный запуск Valheim, заканчивающийся загрузкой мира и строкой сессии.

Каждая строка имеет вид [Level : Source] text. Источник - BepInEx для загрузчика, имя плагина для его собственных сообщений, Unity Log для сообщений самого Unity и иногда HarmonyX для библиотеки патчинга, которой пользуются моды. Уровень - один из Fatal, Error, Warning, Message, Info или Debug.

Нет баннера: Doorstop и прелоадер#

Если LogOutput.log отсутствует или его время старше последнего запуска, BepInEx не запускался. Сервер стартовал как обычный ванильный Valheim. Все симптомы, связанные с модами, вытекают из этого, поэтому исправляйте это в первую очередь.

Doorstop - небольшой инжектор, заставляющий Unity загрузить BepInEx раньше игры. В Linux он работает через переменные окружения, которые задаёт start_server_bepinex.sh; в Windows это winhttp.dll и doorstop_config.ini в корне сервера. Полную структуру показывает статья моды Valheim с BepInEx на сервере. Сбои по сообщению, которое вы видите в консоли:

`ERROR: ld.so: object 'libdoorstop_x64.so' from LD_PRELOAD cannot be preloaded` - библиотеки нет там, куда указывает LD_LIBRARY_PATH. Обычно скопировали папку-обёртку архива, и в корне оказалась BepInExPack_Valheim/doorstop_libs вместо doorstop_libs.

`/bin/bash^M: bad interpreter` - у стартового скрипта окончания строк Windows, обычно после правки на ПК и загрузки. Верните как было:

bash
$ sed -i 's/\r$//' start_server_bepinex.sh$ chmod +x start_server_bepinex.sh

`Permission denied` при запуске скрипта - при передаче он потерял бит исполнения. Исправляет chmod выше.

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

Windows: нет баннера - winhttp.dll отсутствует в папке с valheim_server.exe, либо в doorstop_config.ini он отключён. Имена ключей в ini различаются между Doorstop 3 и 4; откройте файл и найдите переключатель включения и путь к целевой сборке, который должен указывать на BepInEx\core\BepInEx.Preloader.dll.

Если баннер появился, но запуск останавливается между Preloader started и Chainloader ready, проблема в патчере, а не в плагине. Патчеры лежат в BepInEx/patchers и выполняются до загрузки кода игры. HookGenPatcher, который нужен Jotunn, - обычный патчер на серверах Valheim. Патчер, собранный под другую версию игры, даёт сбой именно здесь, как и тот, что положен в plugins, где ему не место: ошибка обычно называет сборку.

Недостающие зависимости и пропущенные плагины#

Как только chainloader работает, BepInEx прямо сообщает о каждом отвергнутом плагине. Эти строки - самая дешёвая диагностика во всём логе.

bash
$ grep -nE "Could not load|Skipping|Error loading" BepInEx/LogOutput.log
Строка начинается сЗначениеРешение
Could not load [X] because it has missing dependencies:Не загружен плагин, который нужен XУстановите названную зависимость, не ниже показанной версии
Could not load [X] because it is incompatible with:X объявляет конфликт с установленным плагиномУберите один из двух
Skipping [X] because of process filtersX помечен для другого процесса, обычно клиентаНе ставьте его на сервер
Skipping [X] с упоминанием более новой версииДве копии одного плагинаУдалите старую копию
Error loading [X]X найден, но выбросил исключение при запускеПрочитайте исключение под строкой

Строка о недостающей зависимости называет её по GUID, а не по отображаемому имени, и часто с минимальной версией:

code
[Error  :   BepInEx] Could not load [EpicLoot 0.10.3] because it has missingdependencies: com.jotunn.jotunn (v2.20.0 or newer)

Этот GUID запросил зависимый мод. Найдите страницу мода на Thunderstore или его список зависимостей, чтобы сопоставить GUID с пакетом. Две ситуации дают эту строку, даже если вы уверены, что зависимость установлена. Либо сама зависимость не загрузилась раньше в логе - найдите её собственную строку Could not load или Error loading - либо установлена версия старее минимальной. А поскольку Jotunn нужен HookGenPatcher, HookGenPatcher не в той папке может сломать Jotunn, и каждый мод на Jotunn после него сообщит о недостающей зависимости. Исправьте первое звено цепочки, и остальное обычно проходит.

Строка о фильтре процесса сообщает, что мод клиентский. Моды, имеющие смысл только при наличии экрана, часто объявляют, что работают в valheim.exe. На valheim_server их пропускают с предупреждением, это безвредно; уберите их с сервера, чтобы лог был тише.

Исключения: находим виновный мод#

Исключение в логе - это блок: строка заголовка с типом исключения, затем стек вызовов, самые свежие вызовы первыми. Большинство выглядит хуже, чем есть на самом деле.

code
[Error  : Unity Log] MissingMethodException: Method not found:void Humanoid.UseItem(Inventory,ItemDrop/ItemData,bool)Stack trace:ExampleMod.Patches.Humanoid_UseItem_Patch.Prefix (Humanoid __instance) ...(wrapper dynamic-method) Humanoid.DMD<Humanoid::UseItem>(Humanoid, ...)

Трассировка выше выдумана, но типична по форме. Как её читать:

  1. Тип. MissingMethodException, MissingFieldException и TypeLoadException означают, что мод скомпилирован под другую версию игры и вызывает код, который изменился. После патча Valheim они ожидаемы, пока авторы не обновятся. Никакая конфигурация этого не исправит.
  2. Мод. Просмотрите стек вниз в поисках пространства имён, которое не относится ни к классам Valheim, ни к UnityEngine - здесь это ExampleMod.Patches. Это мод, чей код выполнялся.
  3. Патчируемый метод. Строки с DMD<...> - методы игры, которые мод запатчил через Harmony. Имя метода говорит, что делал игрок (использовал предмет, ставил постройку), и это помогает, когда нужно воспроизвести сбой.

Самое расплывчатое - NullReferenceException. В стеке мода это обычно значит, что мод ждал того, чего нет: отсутствующее значение конфигурации, предмет из мода, который не загрузился, или объект, который клиентский мод ожидал на безголовом сервере. Прежде чем подозревать сам мод, проверьте, загрузились ли его зависимости.

Одно исключение при запуске, за которым следует обычный Chainloader startup complete и рабочий сервер, может быть косметическим. Но то же исключение, повторяющееся каждые несколько секунд, - нет: оно тратит CPU и забивает диск, и названный в нём мод нужно убрать или починить. Как отделять шум от сигнала, подробнее в статье логи игровых серверов: разбор.

Шум, который можно игнорировать#

Безголовый сервер пишет вещи, которые звучат тревожно и ничего не значат. На сервере Valheim это обычно безвредно:

  • Сообщения о шейдерах, графических устройствах или звуке. У сервера нет GPU и звука, Unity так и говорит.
  • Строки Fallback handler could not load library в Linux для библиотек, которые безголовому серверу никогда не нужны.
  • Предупреждения мода о том, что необязательная интеграция не найдена - например, мод отмечает, что другой мод, с которым он может работать, не установлен.
  • Строки Steam об ID самого сервера и сессии, которые относятся к Valheim, а не к BepInEx.

Узнайте, что ваш сервер пишет в хороший день. Скачайте один чистый LogOutput.log после удачного запуска и сохраните его. Когда что-то сломается, сравните новый лог с заведомо рабочим; первая отличающаяся строка обычно и есть начало проблемы.

Деление пополам для сломанного набора модов#

Иногда лог не указывает на один мод. Сервер, падающий через двадцать минут, ошибка без мода в трассировке, мир, странно ведущий себя только при всех установленных модах. Тогда вы перестаёте читать и делите пополам: уберите половину модов, проверьте и продолжайте делить ту половину, где сбой.

Порядок действий:

  1. Сделайте backup мира и всей папки BepInEx.
  2. Направьте сервер на копию мира (другое имя -world со скопированными файлами .db и .fwl) или на новый тестовый мир, если сбой от него не зависит.
  3. Создайте папку вне plugins, например BepInEx/plugins_off. Именно вне: BepInEx загружает .dll и из вложенных папок plugins, так что plugins/disabled ничего не отключает.
  4. Переместите туда половину модов. Библиотеки вроде Jotunn оставьте на месте и держите каждый мод вместе с его зависимостями: мод, оторванный от своей библиотеки, даёт лишь строку о недостающей зависимости и ничему вас не учит.
  5. Запустите сервер и воспроизведите сбой.
  6. Если сбой пропал, он в перемещённой половине: поменяйте половины местами. Если остался - в той, что загружена. В любом случае делите подозреваемую группу снова.
  7. Остановитесь, когда в группе остался один мод. Проверьте, вернув всё, кроме него.

Нужное число раундов - двоичный логарифм числа модов, округлённый вверх.

Установлено модовРаундов до одного
83
164
325
646

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

Если хост автоматически перезапускает сервер после сбоя, набор модов, падающий при старте, может уйти в цикл. На RE:NODE три перезапуска после сбоя за час выводят предупреждение на странице сервера и открывают тикет, поэтому остановите сервер перед делением пополам, а не давайте ему ходить по кругу; цикл объясняет статья почему ваш игровой сервер всё время перезапускается.

Как поделиться логом, чтобы получить помощь#

Авторы модов и помощники из сообщества попросят полный LogOutput.log, а не скриншот последних строк. Полезный вариант:

  • Весь файл, с первой строки. Причина рядом с началом; видимый конец - это последствия.
  • Из сбойного запуска, взятый до того, как перезапуск его перезаписал.
  • Обе стороны, когда клиента выкидывает или он падает при входе: лог сервера и собственный LogOutput.log игрока из его профиля.
  • Список ваших модов с версиями, которым уже являются строки Loading:
bash
$ grep -o 'Loading \[[^]]*\]' BepInEx/LogOutput.log | sort

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

FAQ#

Почему LogOutput.log пуст или отсутствует?

BepInEx не запустился. Либо сервер запустили без Doorstop (не та команда запуска, отсутствуют переменные окружения в Linux, нет winhttp.dll в Windows), либо BepInExPack распаковали в подпапку. Исправьте внедрение, и при следующем запуске лог появится.

В логе нет ошибок, но мод ничего не делает. Что дальше?

Проверьте, есть ли у него строка Loading. Если есть, мод загрузился, а причина в другом: он клиентский и установлен только на сервере, по умолчанию отключён в своей конфигурации или его настройки синхронизируются откуда-то, что вы не редактировали.

Безопасно ли удалять LogOutput.log?

Да. При следующем запуске BepInEx создаст новый. Сначала скопируйте его, если вы как раз ищете сбой.

Как найти, какой мод тормозит сервер?

Лог помогает, только если мод выбрасывает ошибки, что видно по повторяющемуся одному и тому же исключению. Иначе делите пополам с тестовым миром и секундомером или следите за CPU на графиках сервера, убирая подозреваемых.

Что включает число в строке лога N plugins to load?

Каждый плагин, который BepInEx нашёл в plugins и его подпапках, включая те, которые затем будут пропущены или не загрузятся. Число больше, чем ваше число модов, означает дубликаты или забытые файлы.