Настройка выделенного сервера Source под Linux, часть 1

В данном руководстве будет описана установка и настройка одновременной работы нескольких выделенных игровых серверов Steam под Linux на примере игры Team Fortress 2.


  • Введение
  • Установка клиента Steam и сервера Team Fortress 2
  • Базовая настройка серверов
    • Теория
    • Практика
    • Сетевые настройки
    • Скрипты запуска сервера
  • Обновление серверов
    • Автоматическое
    • Периодическое обновление
    • Только проверка

Введение

Нам понадобится:


  • сервер с процессором, диском и памятью, способными потянуть все игровые сервера
  • нормальный канал в интернет. Не dialup. Не ADSL.
  • установленный веб-сервер, в нашем случае — nginx
  • установленный sql-сервер, в нашем случае — mysql (mariadb)
  • возможность запускать задачи по расписанию (cron)
  • php с модулями
  • root доступ на отдельных этапах настройки
  • достаточно места на диске для:
    • игрового сервера — свыше шести гигабайт
    • логов (а их будет много и разных)
    • записей (replay)
    • sql баз данных
    • пользовательских карт, звуков, моделей и так далее.

Всё нижеследующее описывается применительно к отдельному серверу, физическому или виртуальному, с установленным и настроенным Linux, доступом в консоль. Во всех примерах у сервера ip адрес 192.0.2.0, у нашего клиентского компьютера 198.51.100.0


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


   # useradd --user-group --create-home --comment "Source dedicated server" game

Поскольку мы будем запускать ряд скриптов по расписанию, то проверим, может ли пользователь game создавать свой crontab файл:


   # su - game
   $ crontab -e

Если открылось окно редактора, то хорошо, может. Если же на экран вывелось что-то вида:


   cannot chdir(/var/spool/cron), bailing out.
   /var/spool/cron: Permission denied

то не может. Тогда, в зависимости от используемой программы cron и её настроек, разрешаем пользователю (предварительно выйдя из-под game назад в root) создавать свой crontab файл.


Итак, пользователь создан, авторизация настроена. Закрываем root сессию, продолжаем работать как game.


Установка клиента Steam и сервера Team Fortress 2

Нашу цель по установке и настройке одновременной работы нескольких игровых серверов можно достичь разными способами. В простейшем случае — создавая отдельные экземпляры серверов, каждый в своём каталоге. Это, ценой неэффективного использования дискового пространства (если файловая система или хранилище данных не используют дедупликацию) и повышенного расхода траффика на скачивание одинаковых обновлений даёт возможность независимой настройки, обновления и управления серверами, хотя при использовании одного ip адреса всеми игровыми серверами всё же придётся им использовать разные порты. Другой способ — использование единого каталога для игры, но с индивидуальными настройками игровых серверов. Этим путём мы и пойдём.


Если у нас 64-битный дистрибутив Linux, то необходимо установить дополнительные библиотеки совместимости (из-под пользователя root). Какие именно — гуглится по фразе steamcmd x64 ВАШ_ДИСТРИБУТИВ. Для Ubuntu 13.10×64, например, apt-get install lib32gcc1, для ArchLinux — pacman -S lib32-gcc-libs (при включённом репозитории multilib в /etc/pacman.conf), для CentOS — yum install glibc.i686 libstdc++.i686 и так далее.


Если их не устанавливать, будут выдаваться ошибка вида:


   ./steamcmd.sh: line 29: /home/game/Steam/linux32/steamcmd: No such file or directory

либо


   ./steamcmd.sh: /home/game/Steam/linux32/steamcmd: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory

Устанавливать клиента Steam будем в одноимённый каталог в домашней директории пользователя game, а саму игру в каталог tf2. Предполагается, что в /etc/fstab раздел с /home монтируется без noexec и там достаточно свободного места.


Создаём каталоги для наших серверов и переходим в первый:


   $ mkdir ~/Steam
   $ mkdir ~/tf2
   $ cd ~/Steam

Скачиваем консольный клиент Steam, распаковываем архив.


   $ wget http://media.steampowered.com/client/steamcmd_linux.tar.gz
   $ tar -xvzf steamcmd_linux.tar.gz

Для большей наглядности разобьём следующий запуск steamcmd.sh на два. Сначала запустим процедуру самообновления:


   $ ./steamcmd.sh +quit

Клиент Steam должен обновиться. В случае каких-то проблем читаем логи в ~/Steam/logs.


Теперь установим выделенный сервер игры:


   $ ./steamcmd.sh +login anonymous +force_install_dir ~/tf2/ +app_update 232250 validate +quit

Число »232250» в параметрах командной строки — это appid, идентификатор приложения, в нашем случае Team Fortress 2 dedicated server. Подробнее команды описаны в разделе «Обновление серверов».


Если всё ok, то бодренько начнётся загрузка:


   Redirecting stderr to '/home/game/Steam/logs/stderr.txt'
   ...
   Connecting anonymously to Steam Public...Logged in OK
   Waiting for license info...OK
    Update state (0x3) reconfiguring, progress: 0.00 (0 / 0)
    Update state (0x11) preallocating, progress: 8.28 (561715882 / 6785978023)
    Update state (0x61) downloading, progress: 0.20 (13671159 / 6785978023)
    Update state (0x61) downloading, progress: 0.70 (47497460 / 6785978023)
    ...
    Update state (0x61) downloading, progress: 99.96 (6783415033 / 6785978023)
    Update state (0x81) committing, progress: 7.66 (519615292 / 6785978023)
   Success! App '232250' fully installed.

Несколько минут, и у нас для Team Fortress 2 будет скачано шесть с половиной гигабайт (по состоянию на октябрь 2016 г.).


Переходим в папку ~/tf2 и пробуем запустить игру вручную, посмотрим, как оно.


   $ cd ~/tf2
   $ ./srcds_run -game tf +map cp_cloak

На консоли должно появится что-то вроде:


   Auto detecting CPU
   Using default binary: ./srcds_linux
   Server will auto-restart if there is a crash.

   WARNING: Failed to load 32-bit libtinfo.so.5 or libncurses.so.5.
     Please install (lib32tinfo5 / ncurses-libs.i686 / equivalent) to enable readline.

   Using Breakpad minidump system. Version: 3475087 AppID: 232250
   Setting breakpad minidump AppID = 232250
   Using breakpad crash handler
   Loaded 7510 VPK file hashes from /home/game/tf2/tf/tf2_textures.vpk for pure server operation.
   ...
   Network: IP 192.0.2.0, mode MP, dedicated Yes, ports 27015 SV / 27005 CL
   Initializing Steam libraries for secure Internet server
   ...
   Connection to Steam servers successful.
      Public IP is 192.0.2.0.
   Assigned anonymous gameserver Steam ID [A:1:1724597452:5521].
   VAC secure mode is activated.
   Received 3825164 bytes item schema version DBDD1115 direct data; update is queued.

Можно уважить просьбу, установив библиотеку ncurses-libs.i686. А в остальном всё хорошо. Убедимся, что в строках 13 (Network: …) и 17 (Public IP …) сервер выбрал правильный IP.


На ошибки про »/home/game/.steam/sdk32/steamclient.so: cannot open shared object file: No such file or directory» не обращаем внимания, это нормально. Впрочем, можно и поправить:


   $ mkdir -p ~/.steam/sdk32
   $ ln -s ~/Steam/linux32/steamclient.so ~/.steam/sdk32

Запускаем у себя на компьютере Team Fortress 2, вызываем консоль (~), затем connect 192.0.2.0:27015 (Либо сразу steam://connect/192.0.2.0:27015 — можно потом создать ярлык на рабочем столе). Начинаем подключаться к игровому серверу, а на консоли сервера в это время вывелась строчка вида


   Client "Ich" connected (198.51.100.0:42380).

Если подключиться не получилось, то проверяем, на правильном ли интерфейсе «слушает» сервер. При наличии файервола проверяем, открыты ли нужные порты согласно руководства Valve. В случае более сложных сетевых конфигураций (сервер за NAT и тому подобное) обращаемся к соответствующим руководствам.


Останавливаем игровой сервер командой quit, впечатав её в его консоль, возвращаемся в командную строку и начинаем настройку.


Базовая настройка серверов

Теория


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


По умолчанию сервер использует несколько основных файлов с настройками, которые ищет в ~/tf2/tf/cfg/: autoexec.cfg — выполняется единожды при старте сервера, server.cfg — при запуске любой карты, <имя_карты>.cfg — при запуске соответствующей карты.


Так же, при запуске сервера, в его командной строке можно указать параметр +servercfgfile my.cfg — при этом сервер отныне будет использовать не server.cfg, а my.cfg, и несколько параметров вида +exec file1.cfg +exec file2.cfg +exec file3.cfg — эти файлы будет выполнены единожды при старте сервера, сразу после autoexec.cfg.


Вдобавок, ещё до проверки основного каталога, сервер при запуске ищет в ~/tf2/tf/custom файлы с расширением .vpk и структуры каталогов вида my_dir/cfg/, my_dir/maps/, my_dir/materials/ и тому подобное и найденные там файлы использует вместо одноимённых стандартных.


Но и это не всё. В обновлении Team Fortress 2 от 14 мая 2013 года появился новый параметр командной строки -insert_search_path. Он служит для добавления пользовательской структуры каталогов (аналогично custom/), но с возможностью указания абсолютного пути, то есть не обязательно внутри серверного каталога ~/tf2/tf/. Раньше для это приходилось исхитряться, а сейчас достаточно в командной строке srcds_run указать -insert_search_path /var/dir1 и этот каталог будет использоваться как поисковый путь (/var/dir1/maps, /var/dir1/cfg, …) до путей в custom/ и до основного каталога с файлами конфигураций ~/tf2/tf/cfg/. В -insert_search_path можно указать несколько каталогов через запятую. Причём каталоги будут обрабатываться в том порядке, в каком они перечислены, в отличие от структуры каталогов в custom/, где они обрабатываются по алфавиту.


То есть, если у нас есть несколько файлов server.cfg в разных каталогах:


   ~/tf2/tf/cfg/server.cfg
   ~/tf2/tf/custom/my_files/cfg/server.cfg
   ~/tf2/tf/custom/another/cfg/server.cfg
   /var/dir1/cfg/server.cfg

и в командной строке сервера мы вдобавок укажем -insert_search_path /var/dir1, то при запуске сервера и выполнении в консоли и скриптах команд вида exec server.cfg, этот файл сначала будет искаться в /var/dir1/cfg, затем в custom/another/cfg/, далее в custom/my_files/cfg/ (каталоги в custom/ перебираются по алфавиту) и напоследок в основном cfg/. Это относится не только к server.cfg, но и к motd.txt, картам и пр. Подробнее про поисковые пути можно почитать (и поковырять настройки) в ~/tf2/tf/gameinfo.txt — там есть и про настройки путей в зависимости от системного языка, не освещённые здесь и много всего интересного.


Посмотреть очерёдность перебора поисковых путей очень просто — достаточно в консоли запущенного сервера ввести команду path:


   path
   ---------------
   Paths:
   "maps/cp_cloak.bsp" "GAME" (map)
   "/home/game/tf2/bin/" "EXECUTABLE_PATH"
   "/home/game/tf2/" "BASE_PATH"
   "/var/dir1/" "GAME"
   "/var/dir1/" "MOD"
   "/home/game/tf2/tf/custom/another/" "GAME"
   "/home/game/tf2/tf/custom/another/" "MOD"
   "/home/game/tf2/tf/custom/my_files/" "GAME"
   "/home/game/tf2/tf/custom/my_files/" "MOD"
   и так далеее, далее, далее

Так же не забываем про файлы настроек вида <имя карты>.cfg. Кроме того есть replay.cfg, sourcemod.cfg, ммм… да тысячи их!


Такой зоопарк позволяет при настройке индивидуальных конфигураций для серверов выстрелить себе в ногу разнообразными способами. А так как srcds — молодой, динамически развивающийся сервер, то он может доставить немало весёлых часов в поисках ответа на вопрос «А почему ВНЕЗАПНО у игроков перестали скачиваться пользовательские карты. Даже через slow download, не говоря уж о fast… Два года всё было нормально…»


Из всего предложенного богатства выбора, мы остановимся на указании файлов конфигурации в +exec и +servercfgfile в параметрах запуска.


Необходимо учитывать, что любые комплектные файлы, установленные при инсталляции в ~/tf2 могут быть изменены при очередном обновлении сервера, в том числе и файлы в ~/tf2/tf/cfg. Поэтому мы не будем напрямую задействовать имеющиеся файлы конфигурации, а станем создавать, пусть даже и на их основе, но свои.


То есть вместо использования уже существующего, комплектного файла со списком карт для ротации, например, +mapcyclefile mapcycle_quickplay_cp.txt, пусть даже на данный момент он нас полностью устраивает, мы скопируем его в свой mapcycle.txt и будем подключать его.


Изменённые либо удалённые нами комплектные файлы (не только конфигурации, а любые) могут быть возвращены в своё исходное состояние путём запуска обновления игрового сервера с параметром «validate» — steamcmd.sh +login anonymous +force_install_dir ~/tf2/ +app_update 232250 validate +quit. Тогда, даже если как такового нового обновления для нас нет, будет осуществлена проверка контрольных сумм всех комплектных файлов, и, при несовпадении, изменённые файлы будут скачаны заново.

Практика


В нашем примере мы будем настраивать два игровых сервера:


  • первый — публичный, с официальными картами, без модификаций.
  • второй — приватный, с пользовательскими картами, ботами, меняющими игровой процесс модификациями. Но с включённым Valve Anti-Cheat, конечно.

Создадим каталог для хранения файлов с настройками серверов. Заодно сделаем каталог для логов. На данный момент у нас уже есть логи клиента Steam, поэтому сразу же сделаем туда ссылку:


   $ mkdir ~/cfg
   $ mkdir ~/log
   $ ln -s ~/Steam/logs ~/log/steam

Мы по возможности все файлы настроек будем создавать в ~/cfg и символьными ссылками раскладывать в соответствующие каталоги сервера. Такое размещение позволит заметно упростить процедуру резервного копирования и восстановления сервера, и уменьшить смешивание настроек разных серверов, хотя полностью избежать этого не удастся.


Настройки можно условно сгруппировать в три категории:


  1. Параметры, которые должны быть указаны только в командной строке запуска сервера. Пример — maxplayers и sv_pure при значении равном двум
  2. Параметры, которые необходимо указывать до загрузки карт — либо в autoexec.cfg, либо в подключаемых в командной строке +exec file.cfg. Пример — mapcyclefile, motdfile, tv_enable, да много их
  3. Все остальные, которые можно указывать в server.cfg и прочих файлах.

Но в командной строке сервера очень много не укажешь как из-за ограничения по максимальной длине, так и из соображений безопасности — при отсутствии должным образом закрученных гаек, другие пользователи на вашем Linux сервере с доступом в шелл могут видеть процессы и командные строки друг друга — cat /proc//cmdline с такими деликатными параметрами, как rcon_password, tf_serveridentity<...>, sv_setsteamaccount, sv_password и так далее.


Таким образом мы для начала будем использовать всего-навсего пять файлов для наших настроек — общие настройки для обоих серверов в файле autoexec.cfg, индивидуальные настройки первого сервера — autoexec1.cfg и server1.cfg, второго — autoexec2.cfg и server2.cfg. Целесообразность разделения индивидуальных настроек по двум файлам диктуется как вышеприведённым делением параметров на три категории, так и необходимостью использования файлов (типа server.cfg), которые выполняются при каждой смене карты — для восстановления параметров, изменённых в индивидуальных файлах настроек карт, либо вручную в консоли, либо по cron’у, либо иным способом. Ведь файлы типа autoexec.cfg выполняются лишь при старте игрового сервера.


Нельзя не упомянуть три очень полезные команды. Первая — echo "Какое-нибудь сообщение, выводимое на консоль сервера". При использовании в начале каждого файла конфигурации позволяет наглядно видеть очерёдность выполнения различных файлов, в случае анализа неочевидного поведения сервера. Вторая — differences, при вводе в консоли сервера показывает все переменные, значения которых отличны от значений по умолчанию. Облегчает поиск ответа на вопрос «Почему всё не так? Вроде всё как всегда…». Третья — exec  — позволяет вызывать одни файлы конфигурации из других. При вдумчивой настройке, да в сочетании с возможностью замены файлов по cron и вкупе с возможностью их запуска из скриптов (посредством tmux send-keys — пример в скрипте update.sh в разделе «Обновление серверов») позволяет превратить игровой сервер в живой организм, живущий собственной жизнью.

Детальная настройка внутренней конфигурации игрового сервера здесь описываться не будет — у каждого она своя, остановимся лишь на моментах, связанных с одновременной работой двух серверов.


Если у вас уже есть готовые файлы настроек для одинокого сервера, то можно начать с них, а если нет (ну, мало ли — наш первый игровой сервер), то можно погуглить по фразе настройка server.cfg для tf2. Единственно что могу посоветовать — не искать чей-нибудь максимально навороченный файл конфигурации десятилетней давности, в котором перечислены все возможные, в том числе и уже устаревшие параметры, причём подавляющее большинство — со значениями по умолчанию и описаниями, взятыми из cvarlist, а искать актуальные и максимально документированные описания, хотя это может быть непросто, да.


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


Если всё же хочется узнать «все-все-все» серверные публичные команды и переменные, то в консоли запущенного сервера достаточно ввести:


   cvarlist log allcvars.txt
   cvar list
   --------------
   _resetgamestats    : cmd : : Erases current game stats and writes out a blank stats file
   _restart           : cmd : : Shutdown and restart the engine.
   ...
   --------------
   1908 total convars/concommands

и в файле ~/tf2/tf/allcvars.txt будут перечислены все консольные переменные, зачастую с краткими описаниями. Можно выводить только команды с определённым префиксом, например, cvarlist tf_, cvarlist sv_. Можно искать по подстроке — find log. При этом поиск выполняется как по имени, так и по описанию.


Итак, создаём наши файлы конфигурации.


Стоит иметь в виду, что многие команды зависят друг от друга, и в ряде случаев важна их последовательность. Так, например, если сначала включить запись логов в файл (log on), а потом начать указывать в какой каталог (sv_logsdir) и под каким именем (sv_logfilename_format) — результаты будут не соответствовать ожиданиям.

В файле ~/cfg/autoexec.cfg — он выполняется первым, прописываем настройки, общие для обоих серверов:


autoexec.cfg
// Сообщение на консоль сервера
echo "*** ~/cfg/autoexec.cfg (global)"

// Загрузка списков блокированных игроков, общие для всех серверов
exec banned_user.cfg
exec banned_ip.cfg
writeid
writeip

// Регион, где находится сервер
// -1 - мир, 0 - США восток, 1 - США запад, 2 - Южная Америка, 3 - Европа,
// 4 - Азия, 5 - Австралия, 6 - Ближний Восток, 7 - Африка
sv_region 3

// Настройки логов

// Можно писать логи только в один файл (1),
// либо при каждой смене карт создавать новый (0)
sv_log_onefile 0

// Записывать баны игроков в логи
sv_logbans 1

// Логи могут записываться в файл, выводиться в консоль, транслироваться по UDP.
// Разрешаем запись логов в файл
sv_logfile 1

// Дублировать логи в консоль
sv_logecho 0

// Включать запись логов (log on) мы будем в индивидуальных файлах
// наших серверов - после указания индивидуальных путей (sv_logsdir)

Более подробно команды управления логами рассмотрены в разделе «Логи».

Создадим (пока) пустые файлы banned_user.cfg и banned_ip.cfg


   $ touch ~/cfg/banned_user.cfg ~/cfg/banned_ip.cfg

В файле ~/cfg/autoexec1.cfg прописываем настройки для первого сервера:


autoexec1.cfg
// Сообщение на консоль сервера
echo "*** ~/cfg/autoexec1.cfg"

// Название сервера, как оно будет видно игрокам в браузере игровых серверов
hostname Public Server No 1

// Пароль для удалённой консоли.
// Понадобится для сервера статистики и удалённого управления
rcon_password rconPasswordServer1

// Начальная карта. Обязательно должна быть указана или здесь
// или в командной строке сервера. Командная строка приоритетнее
map cp_granary

// sv_allow_point_servercommand

// Файлы с message of the day
motdfile motd1.html
motdfile_text motd1.txt

// Файл с именами карт для ротации
mapcyclefile mapcycle1.txt

// Каталог для логов первого сервера
sv_logsdir /home/game/log/server1

// Включаем ведение логов
log on

Про файлы motd и mapcyclefile будет сказано чуть ниже. Каталог для логов сервер создаст сам.


А на второй сервер мы установим карту cp_orange_x3, не входящую в стандартную поставку Team Fortress 2. Простейший способ установки пользовательских карт — это положить файл с картой в ~/tf2/tf/maps, либо в каталог в одном из поисковых путей. Но есть ещё способ подключения сторонних карт. Если такая карта представлена в Steam Workshop, то мы можем ссылаться на неё как на «workshop/», либо «workshop/<имя карты>.ugc» и в команде map и в файле mapcycle. Тогда при запуске игры наш сервер скачает её с серверов Valve, а при подключении игрока, его компьютер сам скачает карту оттуда же. При каждой смене карты, она будет проверяться на наличие обновлений. При использовании нестандартных карт только из Steam Workshop, становится ненужным включение Fast Download. Но обратная сторона медали — появляется зависимость ещё и от Workshop серверов.

Итак, открываем в браузере Steam Workshop по ссылке выше, в строке поиска вводим «cp_orange_x3», в результатах поиска переходим на страницу карты — https://steamcommunity.com/sharedfiles/filedetails/? id=454299390. Из этого url берём числовой id и прописываем его в нашем autoexec2.cfg в формате «workshop/454299390» либо «workshop/cp_orange_x3.ugc454299390». Второй вариант нагляднее.


В файле ~/cfg/autoexec2.cfg прописываем настройки для второго сервера:


autoexec2.cfg
echo "*** ~/cfg/autoexec2.cfg"

hostname Private Server No 2

rcon_password rconPasswordServer2

//map workshop/454299390
map workshop/cp_orange_x3.ugc454299390

sv_allow_point_servercommand always

motdfile "motd2.txt"

mapcyclefile "mapcycle2.txt"

sv_logsdir /home/game/log/server2

log on

Ещё один маленький момент. Для каждой карты можно создать файл-спутник <имя карты>.cfg — для команд, выполняемых сервером при старте этой карты, сразу после выполнения server.cfg. Для стандартных карт файл должен находится в ~/tf2/tf/cfg. А для карт из Steam Workshop, имя файла конфигурации должно выглядеть как »<имя карты>.ugc.cfg» и находиться ему полагается в ~/tf2/tf/cfg/workshop. Этот каталог единый для обоих игровых серверов, что следует учитывать, если оба сервера будут использовать одну и ту же карту из Steam Workshop. Для нашей карты cp_orange_x3, у которой id 454299390, полный путь к её файлу конфигурации будет выглядеть как ~/tf2/tf/cfg/workshop/cp_orange_x3.ugc454299390.cfg

Для пользовательских карт возможность выполнения некоторых команд из таких файлов конфигурации регулируется серверной командой sv_allow_point_servercommand, по умолчанию имеющей значение «official» — Allowed for valve maps only. Для разрешения выполнения для любой карты необходимо установить её значение в «always» в autoexec2.cfg


Если захочется просто скачать какую-нибудь карту из Steam Workshop, то в консоли игрового сервера достаточно ввести команду tf_workshop_map_sync . При этом начнётся отслеживание этой карты — при ручном переходе на неё с помощью changelevel wohrkshop/ так же будет проверка на предмет обновления. Посмотреть отслеживаемые карты можно с помощью команды tf_workshop_map_status, ну или в файле ~/tf2/steamapps/workshop{1,2}/appworkshop_440.acf.

В файле ~/cfg/server1.cfg прописываем команды для первого сервера, которые будут выполняться при каждой смене карты:


server1.cfg
// Сообщение на консоль сервера
echo "*** ~/cfg/server1.cfg"

// *** Восстанавливаем значения переменных при смене карты

// Адрес и порт, куда сервер будет транслировать свои логи по UDP для сервера статистики HLstatsX
// Для каждого игрового сервера указываем свой порт
// Нельзя использовать адрес 127.0.0.1 (!)
// Необходим "log on" в каком-нибудь файле конфигурации (у нас установлен в autoexec1.cfg)
logaddress_delall
logaddress_add 192.0.2.0:27500

// Разрешение на использование читерские команды (1 - да, 0 - нет)
sv_cheats 0

Если мы в какой-то момент отключим ведение логов и их попадание в статистику HLstatsX (ну мало ли зачем может понадобится — на отдельной карте для выполнения достижений, либо решили потусить с ботами) командой logaddress_delall в <имя карты>.cfg, или в консоли или как-то ещё, то указание параметра logaddress_add в server1.cfg обеспечит восстановление трансляции логов при смене карты. А команда logaddress_delall предваряет logaddress_add во избежание ругани «logaddress_add: 192.0.2.0:27500 is already in the list»


Читы у нас и так отключены, но при каждой смене карты всё равно устанавливаем sv_cheats в »0» — на случай, если для каких-то целей (генерация навигационной сетки, например) ранее ручками устанавливали в »1».


В файле ~/cfg/server2.cfg прописываем аналогичные команды для второго сервера:


server2.cfg
echo "*** ~/cfg/server2.cfg"

// Обратите внимание - для первого сервера порт был 27500, для второго - 27501 !!!
logaddress_delall
logaddress_add 192.0.2.0:27501

sv_cheats 0

tf_bot_quota 0

Далее создаём файлы со списком карт для ротации. Для первого сервера, на котором мы будем крутить карты лишь режима Control Point, мы за основу берём уже готовый mapcycle_quickplay_cp.txt, который при желании можно подправить.


   $ cp ~/tf2/tf/cfg/mapcycle_quickplay_cp.txt ~/cfg/mapcycle1.txt
   $ dos2unix ~/cfg/mapcycle1.txt
   $ chmod 664 ~/cfg/mapcycle1.txt

Таким образом, в ~/cfg/mapcycle1.txt у нас прописаны карты для ротации на первом сервере:


mapcycle1.txt
cp_5gorge
cp_badlands
cp_coldfront
cp_fastlane
cp_freight_final1
cp_granary
cp_well
cp_yukon_final
cp_foundry
cp_gullywash_final1
cp_process_final
cp_standin_final
cp_snakewater_final1
cp_powerhouse
cp_vanguard
cp_sunshine
cp_metalworks

Для второго сервера файл с картами ~/cfg/mapcycle2.txt создадим вручную. Карту cp_orange_x3 прописываем в том же формате, что и в autoexec2.cfg — «workshop/454299390», либо «workshop/cp_orange_x3.ugc454299390»:


mapcycle2.txt
// Карта cp_orange_x3 с https://steamcommunity.com/sharedfiles/filedetails/?id=454299390
workshop/cp_orange_x3.ugc454299390

Теперь создадим файлы с приветственными сообщениями игрокам. Можно в текстовом формате, можно с html разметкой, можно строку с url. При этом максимальный размер файла ограничен где-то 1–2 Кб.


Для первого сервера создаём ~/cfg/motd1.html с гипертекстовым содержимым:


motd1.html

    
        Message of the day
    
    
        

Welcome to our server!


и текстовый файл ~/cfg/motd1.txt для игроков, у которых отключён показ html motd (cl_disablehtmlmotd 1):


motd1.txt
Welcome!
Have fun and be safe

Для второго сервера в ~/cfg/motd2.txt укажем внешний url, который будет загружен у игроков в motd окне игры:


motd2.txt
http://m.forum.example.org/news.html

Фишка с url срабатывает лишь для motdfile. При указании в motdfile_text, url будет просто показан как текст.


В интернете можно найти различные руководства по созданию MOTD — from Jimo, как вариант ещё одно.


Всё, основные файлы конфигурации на данном этапе созданы, делаем ссылки на них в каталог cfg игрового сервера:


   $ ln -s -v ~/cfg/* ~/tf2/tf/cfg/

Сетевые настройки


При запущенном сервере без параметров (как мы делали это в самом начале), если в другом окне терминала запустить netstat -lpn | grep srcds, то мы увидим:


   tcp     0      0 192.0.2.0:27015    0.0.0.0:*     LISTEN      3456/./srcds_linux
   udp     0      0 192.0.2.0:27005    0.0.0.0:*                 3456/./srcds_linux
   udp     0      0 192.0.2.0:27015    0.0.0.0:*                 3456/./srcds_linux
   udp     0      0 192.0.2.0:27020    0.0.0.0:*                 3456/./srcds_linux
   udp     0      0 192.0.2.0:26901    0.0.0.0:*                 3456/./srcds_linux

Каждый игровой сервер использует свои порты. Они могут задаваться следующими параметрами при запуске srcds:


UDP/27005
+clientport — Game client port


UDP/27015
-port — The port the server advertises to clients


TCP/27015
порт для удалённой консоли, RCON, номер задаётся параметром -port, но использует протокол TCP. Если управление игровым сервером планируется осуществлять исключительно посредством терминального доступа с помощью ssh (а лучше — настроить и забыть), то этот порт с протоколом TCP (не UDP!) можно закрыть, либо вовсе не открыть на файерволе. Но только аккуратно, лишь на внешнем сетевом интерфейсе. Внутри сервера удалённая консоль энергично используется сервером статистики.


UDP/27020
-tv_port — SourceTV port (описан в соответствующем разделе «SourceTV»)


UDP/26901
-steamport — Steam/VAC connection port


Таким образом, для ручной установки этих же портов, используемых по умолчанию, мы в строке запуска первого сервера укажем »-port 27015 -steamport 26900 +clientport 27005 +tv_port 27020». Порт 26900 — это не ошибка, в действительности сервер будет использовать порт на единичку выше.


Для второго сервера надо указать другие значения. В интернете есть советы, что номера портов в подобных мультисерверных конфигурациях лучше увеличивать не последовательно, а через один (27015 → 27017 → 27019 и так далее). Но в нашем случае будем увеличивать последовательно. Вроде и так работает.


Тогда второй сервер будем запускать с параметрами »-port 27016 -steamport 26901 +clientport 27006 +tv_port 27021».


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


   WARNING: Port 27015 was unavailable - bound to port 27016 instead
   WARNING: Port 27005 was unavailable - bound to port 27006 instead
   WARNING: Port 27020 was unavailable - bound to port 27021 instead
   Network: IP 192.0.2.0, mode MP, dedicated Yes, ports 27016 SV / 27006 CL

и будет использовать следующие по порядку. Но всё же мы будем явно указывать номера портов в командной строке, да ещё припечатаем их параметром -strictportbind (описание будет ниже).


Естественно, ничто не запрещает использовать другие номера портов, хоть »-port 50000 +clientport 50001 +tv_port 50002 -steamport 50003», и при этом сервер будет виден через ISteamApps/GetServersAtAddress интерфейс и к нему в принципе можно будет подсоединиться и играть. Но в нашем примере мы будем более традиционны.


Скрипты запуска сервера


В обычных условиях нам придётся иметь дело с двумя скриптами-обёртками:


  1. с консольным клиентом Steam — ~/Steam/steamcmd.sh, который запускает программу linux32/steamcmd. В явном виде используется нами для установки и регулярных обновлений игровых серверов;
  2. с собственно, самим игровым сервером — ~/tf2/srcds_run, который запускает лежащий тут же srcds_linux, а тот уже игру.

Для настройки и отладки, когда приходится часто запускать/останавливать сервера, мы создадим скрипты для запуска — ~/start1.sh и ~/start2.sh. Потом их расширим и переделаем для автозапуска. Для первого сервера, ~/start1.sh:


start1.sh
#!/bin/sh
#
# Запуск первого сервера.

# Путь к каталогу с игрой, где лежит файл srcds_run
GAMEFOLDER=/home/game/tf2

CMDLINE="-port 27015 -steamport 26900 +clientport 27005 +tv_port 27020 -strictportbind \
    +sv_pure 2 -game tf +maxplayers 24 \
    -pidfile ${GAMEFOLDER}/tf/srcds1.pid \
    -ugcpath ${GAMEFOLDER}/steamapps/workshop1 \
    +exec autoexec1.cfg +servercfgfile server1.cfg"

# Запускаем игровой сервер
${GAMEFOLDER}/srcds_run ${CMDLINE}

Пояснения по параметрам (начинаются с »-») и консольным переменным (начинаются с »+»):


-port
порт для игры. Для первого сервера — 27015. При использовании иных портов, как у нас, необходимо не забыть их открыть на файерволе


-steamport
порт для VAC (Valve Anti-Cheat). В действительности будет использоваться на единичку выше. То есть указав 26900, в действительности будет 26901


+clientport
порт для подключения игроков


+tv_port
порт для SourceTV. Если принципиально не будем пользоваться, то можно вместо +tv_port указать параметр -nohltv


-strictportbind
если вышеуказанные порты заняты, то сервер не будет автоматически выбирать следующие свободные, а будет завершаться с ошибкой «ERROR: Port 27015 was unavailable — quitting due to »-strictportbind» command-line flag!». Будет повод почитать логи и найти ошибку.


-ip
ip адрес, на котором будет сервер. Можно указать какой-то конкретный, либо 0.0.0.0 — все интерфейсы. Мы параметр не устанавливаем, так как на нашем сервере только один сетевой интерфейс, с внешним ip


-game
запускаемая игра. У нас — «tf» — Team Fortress 2.


+maxplayers
максимальное количество игровых слотов на сервере. Этот параметр указывается только в командной строке. Значение по умолчанию — 24, может быть увеличено до 32. Для Mann vs. Machine должно быть 32


-pidfile
указывает файл для хранения PID сервера.


-ugcpath
каталог для скачиваемого контента из Steam Workshop. По умолчанию — ~/tf2/steamapps/workshop. Можно указывать как абсолютный путь так и относительный, от каталога ~/tf2/tf. Так как считается, что использование одного workshop каталога для нескольких игровых серверов не поддерживается и может вызвать проблемы, то для каждого сервера указываем свой.


+sv_pure
предназначение этой переменной — уменьшить возможность мошенничества игроков, которые могут у себя на локальном компьютере заменить игровые файлы на читерские (прозрачные текстуры, трассеры у выстрелов, текстуры игроков и так далее). Этот параметр может принимать значения -1, 0, 1, 2. При установке значения sv_pure от 0 и выше, при подключении к нашему серверу игрока, на его компьютере будет осуществляться проверка целостности ключевых файлов его инсталляции игры (контрольная сумма, цифровая подпись), что, очевидно, несколько замедляет подключение игроков. Критерии проверки описаны в pure_server_full.txt, pure_server_minimal.txt и pure_server_whitelist_example.txt из ~/tf2/tf/cfg/. Для установки максимального уровня — sv_pure 2, параметр должен указываться в командной строке srcds_run, чтобы он смог отработать ещё до того, как сервер при запуске начнёт загружать свои .vpk файлы.


+exec
имя файла, который будет выполняться при старте сервера сразу после autoexec.cfg. Может указываться несколько раз.


+servercfgfile
имя файла, который будет использоваться вместо server.cfg — как при запуске сервера, так и при каждой смене карт


+map
имя карты (без расширения). Можно не указывать здесь, но тогда необходимо указать в файле autoexec.cfg (не server.cfg!). Если не задать карту вообще, то сервер войдёт в ступор. Бывают рекомендации указывать этот параметр последним в командной строке. Но мы его не используем, начальную карту будем указывать в autoexec.cfg


Другие параметры командной строки можно посмотреть в Valve Developer Community wiki


Копируем скрипт в ~/start2.sh, корректируем CMDLINE (увеличиваем на единичку номера портов и подправляем имена файлов), сохраняем.


start2.sh
#!/bin/sh

# Запуск второго сервера.

GAMEFOLDER=/home/game/tf2

CMDLINE="-port 27016 -steamport 26901 +clientport 27006 +tv_port 27021 -strictportbind \
    +sv_pure 2 -game tf +maxplayers 24 \
    -pidfile ${GAMEFOLDER}/tf/srcds2.pid \
    -ugcpath ${GAMEFOLDER}/steamapps/workshop2 \
    +exec autoexec2.cfg +servercfgfile server2.cfg"

# Запускаем игровой сервер
${GAMEFOLDER}/srcds_run ${CMDLINE}

Делаем скрипты исполняемыми


   $ chmod u+x ~/start{1,2}.sh

Можно запустить первый сервер (из-под пользователя game, не root!), сразу посмотреть что-как. Наблюдаем за последовательностью отработки файлов конфигурации:


   ...
   *** ~/cfg/autoexec.cfg (global)
   Writing cfg/banned_user.cfg.
   Writing cfg/banned_ip.cfg.
   --------------------------------------------------------
   sv_pure set to 2.
   --------------------------------------------------------
   maxplayers set to 24
   *** ~/cfg/autoexec1.cfg
   Server logging enabled.
   Server logging data to file /home/game/log/server1/L1007000.log
   ...
   Executing dedicated server config file server1.cfg
   Using map cycle file 'cfg/mapcycle1.txt'.
   Set motd from file 'cfg/motd1.html'
   Set motd_text from file 'cfg/motd1.txt'
   Connection to game coordinator established.
   tf_server_identity_account_id not set; not logging into registered account
   *** ~/cfg/server1.cfg
   logaddress_delall:  no addresses in the list
   logaddress_add:  192.0.2.0:27500
   'cp_granary.cfg' not present; not executing.
   Connection to Steam servers successful.
   ...

Плохо, конечно, начинать отношения со лжи. И к серверам это тоже относится. Хотя наш сервер и утверждает, что логи записываются в файл L1007000.log, на самом деле они пишутся в l1007000.log. Разница в регистре первого символа имени —, но для Linux какая существенная! Но, кто предупреждён — тот вооружён. Будем критически относится к декларируемым функциям. И забегая вперёд — не напрасно.


Теперь аналогично запускаем второй сервер, любопытствуем, как он подключит нашу карту из Мастерской.


   .
    
            

© Habrahabr.ru