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 - небольшой загрузчик, который обновляет сам себя при каждом запуске. Скачайте его, распакуйте, запустите один раз и дайте закончиться, прежде чем просить его о чём-либо.
$ 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-битные библиотеки, прежде чем он вообще запустится:
# 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 - её вариация:
$ ./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, что нормально для одного сервера и неуправляемо для трёх.
Когда загрузка закончится, посмотрите, что лежит в каталоге установки помимо игры:
/srv/valheim/ valheim_server.x86_64 steamapps/ appmanifest_896660.acf installed build id, depots, sizeappmanifest_<appid>.acf - запись SteamCMD о том, что, по его мнению, установлено. Это обычный текстовый файл, и в нём лежит идентификатор сборки - единственный надёжный ответ на вопрос «на какой версии этот сервер». Удалите его, и следующий app_update скачает всё заново с нуля, что иногда оказывается самым быстрым исправлением установки, попавшей в состояние, которое не разрешит никакой validate.
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 2 | 730 | 730 |
| Team Fortress 2 | 232250 | 440 |
| Garry's Mod | 4020 | 4000 |
| Left 4 Dead 2 | 222860 | 550 |
| Valheim | 896660 | 892970 |
| Unturned | 1110390 | 304930 |
| Palworld | 2394010 | 1623730 |
| Project Zomboid | 380870 | 108600 |
| 7 Days to Die | 294420 | 251570 |
| DayZ | 223350 | 221100 |
| Arma 3 | 233780 | 107410 |
| Rust | 258550 | 252490 |
| Satisfactory | 1690800 | 526870 |
| ARK: Survival Ascended | 2430930 | 2399830 |
Когда id найти не удаётся, обычно справочником служит SteamDB, а сам SteamCMD тоже подскажет:
Steam> app_info_update 1Steam> app_info_print 896660Так выводятся метаданные приложения, включая список веток и текущий идентификатор сборки каждой. Вывод многословен, и он остаётся авторитетным ответом, когда страница вики расходится с действительностью.
Анонимный вход и игры, которые его отвергают#
login anonymous работает для подавляющего большинства инструментов выделенных серверов. Меньшинству нужен аккаунт Steam, которому принадлежит игра, и обойти это нельзя: чаще всего вам встретятся Arma 3, DayZ и Project Zomboid, а загрузка Workshop для этих игр требует того же аккаунта.
$ ./steamcmd.sh +force_install_dir /srv/dayz \ +login myspareaccount \ +app_update 223350 validate +quitПризнак того, что вы ошиблись здесь, - конкретное сообщение:
ERROR! Failed to install app '223350' (No subscription)«No subscription» означает, что у выполнившего вход нет лицензии на это приложение. Либо вы использовали anonymous там, где он не принимается, либо аккаунт, под которым вы вошли, не владеет игрой.
Три вещи, которые нужно знать, прежде чем вводить на сервере настоящие учётные данные:
- Используйте запасной аккаунт. Купите игру на аккаунте, где больше ничего нет. Установке игрового сервера незачем находиться на аккаунте, с которого вы совершаете покупки.
- Steam Guard нужно один раз пройти интерактивно. С мобильным аутентификатором вы подтверждаете вход на телефоне в первый раз; затем SteamCMD кэширует учётные данные в собственном каталоге конфигурации, и последующие запуски идут без вашего участия. Поэтому скрипт для запуска без присмотра должен хотя бы раз быть запущен вручную.
- Не передавайте пароль в командной строке. Он попадает в историю оболочки и виден в списке процессов. Пусть SteamCMD запросит его сам.
В RE:NODE игры, которым нужен ваш собственный вход в Steam, - среди них Arma 3, DayZ, Project Zomboid и 7 Days to Die - создаются сразу, а затем ждут на вкладке Setup, пока вы не введёте учётные данные. Они хранятся в том виде, в каком вы их ввели, и это честное описание того, что должен делать любой хостер, чтобы запускать SteamCMD от вашего имени, а также причина, по которой совет про запасной аккаунт выше не факультативен.
Обновления, validate и ветки beta#
Обновление - это та же команда ещё раз. SteamCMD сравнивает манифест с установленным и скачивает только изменившиеся фрагменты, так что обычное обновление игры на 20 GB может передать несколько сотен мегабайт.
validate - другое дело. Он хеширует каждый файл установки и заменяет всё, что не совпадает с манифестом. Это правильная реакция на сервер, который падает при запуске после прерванного обновления, на диск, заполнившийся посреди загрузки, или на просьбу разработчика игры. Запускать его при каждом перезапуске большой установки не стоит, потому что каждый раз он читает с диска всю игру.
Ветки - это то, как издатели выпускают экспериментальные сборки. Ветка по умолчанию называется public, а именованная выбирается в строке обновления:
# 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 читает файл скрипта, в котором у команд нет префикса +:
@ShutdownOnFailedCommand 1@NoPromptForPassword 1force_install_dir /srv/valheimlogin anonymousapp_update 896660 validatequit$ ./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 как на единственную проверку успеха. Исторически он не был надёжен в разных версиях. Надёжная проверка - строка, которую он печатает по завершении:
Success! App '896660' fully installed.Ищите её grep в скрипте-обёртке, а её отсутствие считайте сбоем. Если вы автоматизируете это через панель, а не cron, то как выглядит разумное расписание обновлений и перезапусков, описано в статье задачи по расписанию, которые стоит завести.
Одно замечание о размерах, из-за которого случается больше неудачных обновлений, чем из-за чего-либо ещё: SteamCMD размещает загрузку в том же томе, который обновляет, поэтому для обновления сверх существующей установки нужно свободное место примерно в размер изменившихся файлов. Диск, рассчитанный ровно под игру, - это диск, на котором следующее обновление упадёт, часто с вводящей в заблуждение ошибкой о манифесте приложения. Оставляйте свободными 20-30 процентов.
Загрузка Workshop из командной строки#
Элементы Workshop скачиваются по id, относительно app id игры:
$ ./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. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.