RE:NODE

Эксплуатация13 мин чтения

SteamCMD простыми словами: app id, обновления, беты и скрипты

Что такое SteamCMD, как устроены app id, анонимный вход и вход с аккаунтом, что на самом деле делает validate, ветки beta, скрипты обновления без присмотра и все частые ошибки.

1 прочтений

SteamCMD - это клиент Steam, из которого убрали магазин, список друзей и графику. Он существует ради одной задачи на серверах: скачивать и обновлять бесплатные приложения выделенных серверов, которые Valve и другие издатели выкладывают в Steam, и получать для них контент Workshop. Почти каждая инструкция по установке сервера для игры из Steam начинается с одних и тех же четырёх аргументов в одном и том же порядке, и когда вы понимаете, что делает каждый из них - и зачем нужен файл манифеста, который остаётся после установки, - вы можете установить, зафиксировать, переключить ветку и написать скрипт для любого из них. Это и есть такое объяснение, плюс ошибки, на которые приходится большинство сбоев.

Что такое SteamCMD и когда вы с ним сталкиваетесь#

Выделенный сервер для игры из Steam - это, как правило, отдельное бесплатное «приложение» в Steam со своим app id. Это не сама игра. Владеть игрой для скачивания большинства из них не нужно, а со страницы магазина скачать их нельзя, потому что это инструменты, а не товары. Получить их можно через SteamCMD.

Пользоваться им вы будете в четырёх ситуациях:

  • Первая установка. Скачать серверное приложение в выбранную вами папку.
  • Обновления. Та же команда, запущенная снова, скачивает только то, что изменилось, поэтому она есть в каждом скрипте перезапуска, который пишут люди.
  • Контент Workshop. workshop_download_item скачивает конкретный элемент Workshop по id, и именно так серверы Arma 3, DayZ и Squad получают свои моды.
  • Ремонт. Добавление validate сверяет каждый файл с манифестом и заменяет всё, что не совпадает.

Если вы держите серверы на панели, вам, возможно, никогда не придётся вводить что-либо из этого. В RE:NODE установка выполняется при создании сервера - обычно в течение минуты после прохождения платежа, - а значения, которые SteamCMD получил бы аргументами, появляются полями на вкладке Startup. Понимать, что делают эти поля, всё равно стоит десяти минут, потому что в день, когда что-то пойдёт не так, консоль покажет вам вывод SteamCMD дословно, а чтение консоли гораздо проще, когда вы знаете, что означают строки.

Установка#

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

bash
$ sudo useradd -m steam && sudo su - steam$ mkdir ~/steamcmd && cd ~/steamcmd$ curl -sL https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz | tar zxf -$ ./steamcmd.sh +quit

В Windows аналог - steamcmd.zip по тому же пути, распаковывается куда угодно и запускается как steamcmd.exe. В macOS это steamcmd_osx.tar.gz, хотя из macOS почти никто не хостит.

В Linux людей подстерегают две вещи. Первая: SteamCMD - 32-битный бинарный файл, поэтому 64-битной системе нужны 32-битные библиотеки, прежде чем он вообще запустится:

bash
# Debian and Ubuntu$ sudo dpkg --add-architecture i386 && sudo apt update$ sudo apt install lib32gcc-s1          # lib32gcc1 on older releases# RHEL, Rocky, AlmaLinux$ sudo dnf install glibc.i686 libstdc++.i686

Вторая - владелец файлов. Запускайте SteamCMD от обычного пользователя, которому принадлежит каталог установки, а не от root. Установка от root оставляет файлы, в которые служебный аккаунт не может писать, и обновление, которое упадёт через шесть недель, сообщит об ошибке прав доступа, похожей на проблему с диском.

Устройство команды установки#

Вот эта строка, и любая инструкция по играм Steam - её вариация:

bash
$ ./steamcmd.sh +force_install_dir /srv/valheim \    +login anonymous \    +app_update 896660 validate \    +quit

Каждый + выполняет одну команду при запуске, в написанном порядке, и SteamCMD перешёл бы в интерактивное приглашение, если бы не +quit.

АргументЧто делает
+force_install_dir <path>Куда попадут файлы сервера. Должен стоять до app_update
+login anonymousВход без аккаунта. Должен стоять до app_update
+login <user>Вход под настоящим аккаунтом; запрашивает пароль
+app_update <id>Установить или обновить это приложение
validateСверить каждый файл с манифестом и исправить
-beta <branch>Использовать именованную ветку вместо public по умолчанию
-betapassword <pw>Пароль для закрытой ветки
+quitВыйти, а не открывать приглашение
+runscript <file>Выполнить файл с командами вместо ручного ввода

force_install_dir - тот аргумент, на котором спотыкаются. Относительный путь разрешается относительно собственного каталога SteamCMD, а не рабочего каталога вашей оболочки, поэтому +force_install_dir ../valheim означает разное в зависимости от того, где лежит SteamCMD. Используйте абсолютный путь. Если его вообще не указать, файлы окажутся в steamapps/common/<AppName> внутри папки SteamCMD, что нормально для одного сервера и неуправляемо для трёх.

Когда загрузка закончится, посмотрите, что лежит в каталоге установки помимо игры:

code
/srv/valheim/  valheim_server.x86_64  steamapps/    appmanifest_896660.acf      installed build id, depots, size

appmanifest_<appid>.acf - запись SteamCMD о том, что, по его мнению, установлено. Это обычный текстовый файл, и в нём лежит идентификатор сборки - единственный надёжный ответ на вопрос «на какой версии этот сервер». Удалите его, и следующий app_update скачает всё заново с нуля, что иногда оказывается самым быстрым исправлением установки, попавшей в состояние, которое не разрешит никакой validate.

учётные данныефайлы depotсборка записанаworkshop_download_itemsteamcmdupdates itself firstSteamanonymous or an accountforce_install_dirthe server filessteamapps/workshopcontent per app idappmanifest.acfthe installed build id
Куда SteamCMD что кладёт

App id и три их вида, которые вы встретите#

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

  • App id сервера - то, что вы передаёте в app_update. Обычно он принадлежит отдельному инструменту «Dedicated Server».
  • App id игры - то, что вы передаёте в workshop_download_item, потому что контент Workshop принадлежит игре, а не серверному инструменту; он же нужен при создании токена входа игрового сервера Steam.
  • Иногда они совпадают. Самый заметный пример - Counter-Strike 2: сервер устанавливается из приложения 730, того же id, что и игра.
ИграApp id сервераApp id игры
Counter-Strike 2730730
Team Fortress 2232250440
Garry's Mod40204000
Left 4 Dead 2222860550
Valheim896660892970
Unturned1110390304930
Palworld23940101623730
Project Zomboid380870108600
7 Days to Die294420251570
DayZ223350221100
Arma 3233780107410
Rust258550252490
Satisfactory1690800526870
ARK: Survival Ascended24309302399830

Когда id найти не удаётся, обычно справочником служит SteamDB, а сам SteamCMD тоже подскажет:

code
Steam> app_info_update 1Steam> app_info_print 896660

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

Анонимный вход и игры, которые его отвергают#

login anonymous работает для подавляющего большинства инструментов выделенных серверов. Меньшинству нужен аккаунт Steam, которому принадлежит игра, и обойти это нельзя: чаще всего вам встретятся Arma 3, DayZ и Project Zomboid, а загрузка Workshop для этих игр требует того же аккаунта.

bash
$ ./steamcmd.sh +force_install_dir /srv/dayz \    +login myspareaccount \    +app_update 223350 validate +quit

Признак того, что вы ошиблись здесь, - конкретное сообщение:

code
ERROR! Failed to install app '223350' (No subscription)

«No subscription» означает, что у выполнившего вход нет лицензии на это приложение. Либо вы использовали anonymous там, где он не принимается, либо аккаунт, под которым вы вошли, не владеет игрой.

Три вещи, которые нужно знать, прежде чем вводить на сервере настоящие учётные данные:

  1. Используйте запасной аккаунт. Купите игру на аккаунте, где больше ничего нет. Установке игрового сервера незачем находиться на аккаунте, с которого вы совершаете покупки.
  2. Steam Guard нужно один раз пройти интерактивно. С мобильным аутентификатором вы подтверждаете вход на телефоне в первый раз; затем SteamCMD кэширует учётные данные в собственном каталоге конфигурации, и последующие запуски идут без вашего участия. Поэтому скрипт для запуска без присмотра должен хотя бы раз быть запущен вручную.
  3. Не передавайте пароль в командной строке. Он попадает в историю оболочки и виден в списке процессов. Пусть SteamCMD запросит его сам.

В RE:NODE игры, которым нужен ваш собственный вход в Steam, - среди них Arma 3, DayZ, Project Zomboid и 7 Days to Die - создаются сразу, а затем ждут на вкладке Setup, пока вы не введёте учётные данные. Они хранятся в том виде, в каком вы их ввели, и это честное описание того, что должен делать любой хостер, чтобы запускать SteamCMD от вашего имени, а также причина, по которой совет про запасной аккаунт выше не факультативен.

Обновления, validate и ветки beta#

Обновление - это та же команда ещё раз. SteamCMD сравнивает манифест с установленным и скачивает только изменившиеся фрагменты, так что обычное обновление игры на 20 GB может передать несколько сотен мегабайт.

validate - другое дело. Он хеширует каждый файл установки и заменяет всё, что не совпадает с манифестом. Это правильная реакция на сервер, который падает при запуске после прерванного обновления, на диск, заполнившийся посреди загрузки, или на просьбу разработчика игры. Запускать его при каждом перезапуске большой установки не стоит, потому что каждый раз он читает с диска всю игру.

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

bash
# switch to a public test branch$ ./steamcmd.sh +force_install_dir /srv/7dtd +login anonymous \    +app_update 294420 -beta latest_experimental validate +quit# switch back$ ./steamcmd.sh +force_install_dir /srv/7dtd +login anonymous \    +app_update 294420 -beta public validate +quit

Некоторым веткам нужен -betapassword, который разработчик публикует вместе с названием ветки. К ним ко всем применимы два правила. Клиенты и серверы должны быть на одной ветке, а ошибка, когда это не так, обычно выглядит как несовпадение версий и о ветках не упоминает вовсе. И ветка - единственный поддерживаемый способ зафиксировать версию: в SteamCMD нет аргумента «установить сборку 12345», так что если игра не публикует старую ветку, откатиться с его помощью нельзя. Планируйте это до дня обновления, а не во время него, и прочтите что делать, когда обновление мода всё ломает, если сервер с модами.

Скриптовая установка и обновления без присмотра#

Многократный набор одной длинной строки - вот как опечатки попадают в рабочую среду. SteamCMD читает файл скрипта, в котором у команд нет префикса +:

/home/steam/update-valheim.txt
@ShutdownOnFailedCommand 1@NoPromptForPassword 1force_install_dir /srv/valheimlogin anonymousapp_update 896660 validatequit
bash
$ ./steamcmd.sh +runscript /home/steam/update-valheim.txt

Две строки с @ - это настройки, а не команды. @ShutdownOnFailedCommand 1 заставляет SteamCMD остановиться на первой ошибке, а не идти дальше к quit и завершаться так, будто всё хорошо: без неё неудачная загрузка в задании cron выглядит точно так же, как удачная. @NoPromptForPassword 1 не даёт запуску без присмотра зависнуть навсегда на запросе входа.

Стоит знать ещё две настройки:

  • @sSteamCmdForcePlatformType windows скачивает Windows-сборку приложения на хосте с Linux. Так устанавливаются на Linux серверы, у которых есть только Windows-бинарник, - The Forest здесь типичный пример, - для запуска под Wine.
  • @sSteamCmdForcePlatformBitness 64 принудительно выбирает 64-битный depot там, где приложение предлагает оба.

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

code
Success! App '896660' fully installed.

Ищите её grep в скрипте-обёртке, а её отсутствие считайте сбоем. Если вы автоматизируете это через панель, а не cron, то как выглядит разумное расписание обновлений и перезапусков, описано в статье задачи по расписанию, которые стоит завести.

Одно замечание о размерах, из-за которого случается больше неудачных обновлений, чем из-за чего-либо ещё: SteamCMD размещает загрузку в том же томе, который обновляет, поэтому для обновления сверх существующей установки нужно свободное место примерно в размер изменившихся файлов. Диск, рассчитанный ровно под игру, - это диск, на котором следующее обновление упадёт, часто с вводящей в заблуждение ошибкой о манифесте приложения. Оставляйте свободными 20-30 процентов.

Загрузка Workshop из командной строки#

Элементы Workshop скачиваются по id, относительно app id игры:

bash
$ ./steamcmd.sh +force_install_dir /srv/arma3 +login myspareaccount \    +workshop_download_item 107410 463939057 +quit

Элемент попадает в steamapps/workshop/content/<gameappid>/<itemid>/ внутри каталога установки, а манифест steamapps/workshop/appworkshop_<gameappid>.acf записывает, что было получено и когда. Удаление этого файла принуждает к повторной загрузке всего, и это стандартное исправление для элемента, обновившегося в Steam, но отказывающегося обновляться локально.

Анонимный вход для контента Workshop работает в одних играх и не работает в других, а игры, которым для сервера нужен аккаунт-владелец, обычно требуют его и здесь. Кроме того, SteamCMD не умеет раскрывать коллекцию - он понимает только id отдельных элементов. Механика всего этого, включая то, как контент попадает к игрокам и что происходит, когда автор скрывает элемент, от которого вы зависите, описана в статье моды Steam Workshop на выделенных серверах.

Ошибки и что они на самом деле значат#

СообщениеЧто оно означает
Failed to install app 'X' (No subscription)У логина нет этого приложения, либо оно не принимает анонимный вход
Failed to install app 'X' (Invalid Platform)Нет сборки этого depot для данной ОС. Попробуйте @sSteamCmdForcePlatformType
Failed to install app 'X' (Disk write failure)Диск заполнен либо каталог, в который у пользователя нет права записи
Failed to install app 'X' (Missing file permissions)Не тот владелец каталога установки, обычно установка от root
Failed to install app 'X' (Timeout downloading item)Медленная или прерванная передача. Повторите; большим элементам Workshop часто нужны две попытки
Rate Limit ExceededСлишком много попыток входа. Подождите; повторы почаще только удлиняют ожидание
error while loading shared libraries: libstdc++.so.6Нет 32-битных библиотек
Failed to load steamclient.soТа же причина либо частично распакованный SteamCMD
Update state (0x61) downloading и нет прогрессаДиск или сеть, а не Steam. Сначала проверьте свободное место

Два шаблона покрывают большую часть оставшегося. Команда, которая, похоже, ничего не делает, обычно выполнилась до login, потому что force_install_dir и app_update зависят от выполненного входа. А установка, которая раз за разом падает на полпути на одном и том же файле, - гораздо чаще проблема диска, чем проблема Steam.

На хостинге на основе контейнеров есть ещё один способ отказа, который стоит назвать. Если сервер упирается в лимит памяти во время установки, контейнер останавливается, а не уходит в своп, и после этого вы видите наполовину записанный каталог установки. Исправление - повторить установку с validate; общий характер такого поведения описан в статье почему ваш игровой сервер постоянно перезапускается.

FAQ#

Нужно ли владеть игрой, чтобы запустить её выделенный сервер?

Обычно нет. Большинство приложений выделенных серверов скачиваются с login anonymous. Частые исключения - Arma 3, DayZ и Project Zomboid: их серверным инструментам нужен аккаунт Steam, которому принадлежит игра, и то же относится к их загрузкам Workshop.

Что на самом деле делает validate?

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

Можно ли установить конкретную старую версию?

Только если издатель предлагает её как именованную ветку, выбираемую через -beta. В SteamCMD нет аргумента для произвольного идентификатора сборки. Если вам нужна возможность отката, до обновления проверьте, публикует ли игра legacy-ветку.

Куда попадают файлы, если не задать force_install_dir?

В steamapps/common/<AppName> внутри собственной папки SteamCMD. Для одного сервера это нормально, для нескольких - путаница, поэтому в каждой инструкции каталог задан явно. Используйте абсолютный путь, потому что относительные разрешаются относительно каталога SteamCMD, а не вашей оболочки.

Почему мой скриптовый апдейт сообщает об успехе, хотя ничего не скачалось?

Потому что код возврата SteamCMD - ненадёжный сигнал. Добавьте в скрипт @ShutdownOnFailedCommand 1, чтобы он останавливался на первой ошибке, и пусть ваша обёртка проверяет в выводе Success! App 'X' fully installed., а не $?.

Как узнать, на какой сборке мой сервер?

Прочитайте steamapps/appmanifest_<appid>.acf в каталоге установки. В нём записан идентификатор установленной сборки. app_info_print <appid> внутри SteamCMD показывает идентификаторы сборок, которые сейчас опубликованы в каждой ветке, - с ними вы его и сравниваете.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000