Параметри виділеного сервера 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 x64, наприклад,
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. Детальніше команди описані в розділі "Оновлення серверів".
Якщо все ок, то бадьоренько почнеться завантаження:
Redirecting to stderr '/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. Версія: 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/<id>/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 <config>
— дозволяє викликати одні файли конфігурації з інших. При вдумливої налаштуванні, та в поєднанні з можливістю заміни файлів по 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 <id карти>
. При цьому почнеться відстеження цієї карти — при ручному переході на неї з допомогою
changelevel wohrkshop/<id>
так само буде перевірка на предмет оновлень. Подивитися записані карти можна за допомогою команди
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
<html>
<head>
<title>Message of the day</title>
</head>
<body>
<h1>Welcome to our server!</h1>
</body>
</html>

і текстовий файл ~/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 data logging 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 account registered
*** ~/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 якась істотна! Але, хто попереджений — той озброєний. Будемо критично ставиться до декларованих функцій. І забігаючи вперед — не марно.
Тепер аналогічно запускаємо другий сервер, любопытствуем, як він підключить нашу карту з Майстерні.
...
*** ~/cfg/autoexec2.cfg
...
[TF Workshop] Waiting for connection steam
[TF Workshop] Preparing map ID 454299390
[TF Workshop] Map ID 454299390 isn't tracked, adding
...
[TF Workshop] New version available for map, download queued [ workshop/cp_orange_x3.ugc454299390 ]
...
[TF Workshop] Installed subscribed map [ workshop/cp_orange_x3.ugc454299390 ]
[TF Workshop] Successfully prepared client map from workshop [ workshop/cp_orange_x3.ugc454299390 ]
...
'workshop/cp_orange_x3.ugc454299390.cfg' not present; not executing.
...

Добре, годно. У другого сервера ресурси з Steam Workshop скачались в ~/tf2/steamapps/workshop2, і наша карта знаходиться по дорозі ~/tf2/steamapps/workshop2/content/440/454299390/cp_orange_x3.bsp. У рядках вище, "[ workshop/cp_orange_x3.ugc454299390 ]" — це не шлях до карти, а її ім'я. Детальніше описувалося раніше, коли створювали файл autoexec2.cfg
Знову запускаємо на своєму комп'ютері Team Fortress 2, "Find a game" — "Community servers" — "Вибране" — "Додати" — вводимо ip адреса сервера "192.0.2.0" — "Знайти ігри за цією адресою" — бачимо обидва наших сервера. Працює :-). Додамо їх закладки.
Можна подивитися, як видно наші сервера з точки зору майстер-серверів Valve за допомогою інтерфейсу Web API, відкривши в браузері посилання і вказавши ip нашого сервера http://api.steampowered.com/ISteamApps/GetServersAtAddress/v0001?addr=192.0.2.0 — так можна подивитися всі ігрові source сервера на будь-якій адресі, не тільки Team Fortress 2
Зупиняємо сервера (quit, потім Ctrl+C), продовжуємо налаштування.
Завершувати роботу сервера, запущеного допомогою srcds_run, як у наших скриптах, краще всього ввівши спочатку команду
quit
, а коли на екрані з'явиться завершує роботу виду повідомлення "Sat Jun 18 10:28:33 VOST 2016: Server restart in 10 seconds", то тут вже Ctrl+C. Якщо прибити сервер без коректного виходу, то залишаться недописаними логи — сервер буферизують їх висновок по 8 кб. Можна пропустити що-небудь наостанок цікаве.
Оновлення серверів
Зазвичай процедурою оновлення серверів присвячують всього десяток рядків, і, поклавши руку на серце, для більшості конфігурацій цього достатньо, але в нашому випадку приділимо цьому питанню цілий розділ.
Час від часу Valve випускає оновлення як для клієнтів, так і для серверів, і оновлені клієнти часто відмовляються підключатися до необновленным серверів:
Сервер, до якого ви намагаєтеся приєднатися, працює зі старою версією гри
Оновлення для серверів бувають обов'язкові — без установки яких оновлені клієнти не зможуть підключитися до них, і опціональні — їх (не)установка не вплине на можливість підключення гравців. Відрізнити обов'язкові від необов'язкових можна дуже просто — з анонсу відповідальних товаришів з Valve в офіційному списку розсилки https://list.valvesoftware.com/cgi-bin/mailman/listinfo/hlds_linux. Коли вони пишуть, що "Optional TF2 update released" — то це не обов'язкове оновлення. А коли "Mandatory Team Fortress 2 update released" — то це обов'язкова. Серйозно. На момент написання, за їх словами, єдиний офіційний спосіб дізнатися про випуск нового оновлення — це список розсилки hlds_linux.
Оновлювати ігрові сервера можна кількома способами.
Автоматичне
У найпростішому випадку оновлення ігрових серверів ми можемо віддати на відкуп їм самим — включивши параметри запуску обох серверів рядок:
start1.sh
CMDLINE="...
-autoupdate -steam_dir /home/game/Steam -steamcmd_script /home/game/cfg/tf2_update \
...

autoupdate

будуть автоматично інсталювати оновлення сервера. Вимагає наявності двох наступних параметрів
steam_dir

шлях до каталогу, де лежать файли steam.sh і steamcmd.sh
steamcmd_script

скрипт для відновлення, шукається в "-steam_dir", але можна вказати з абсолютним шляхом
насправді, ця тріада параметрів перед кожним (пере)запуском сервера всього лише виконує
./srcds_run +runscript ~/cfg/tf2_update
У каталозі ~/cfg створюємо файл tf2_update — в ньому вкажемо команди для автоматичного оновлення сервера. Ці команди в суті повторюють ті, які ми вказували в командному рядку при інсталяції ігрового сервера.
tf2_update
@ShutdownOnFailedCommand 0
@NoPromptForPassword 1
login anonymous
force_install_dir /home/game/tf2/
app_update 232250
quit

Пояснення по командам:
@ShutdownOnFailedCommand

керівництво Valve рекомендує встановлювати цю змінну в "0" при оновленні декількох ігрових серверів.
@NoPromptForPassword

дана змінна, встановлена в "1", при логіні в Steam відключає інтерактивний запит пароля, якщо він не вказаний у рядку login. Якщо пароль для даного імені користувача все ж таки потрібна, то у вході буде відмовлено.
login <username> [<password>] [<Steam guard сode>]

здійснює логін в Steam. В даному разі повинна бути вказана обов'язково, інакше при запуску буде видавати помилку "ERROR! Failed to request AppInfo update, not online or not logged in to Steam." Першим аргументом можна вказати "anonymous" — здійснюватиметься анонімний вхід. Стосовно до вибраних ігрових серверів, більшість дозволяють підключатися анонімно для інсталяції і установки оновлень, але деякі можуть вимагати вхід імені користувача та пароля. Список серверів з їх вимогами і деякими параметрами можна подивитися в Dedicated Servers List. При неанонимном логін, як зазвичай при вході з нового комп'ютера, на електронну пошту приходить код steam guard, який вказується або тут, або в окремій команді set_steam_guard_code.
set_steam_guard_code <сode>

вказується код steam guard. Для анонімного логіна не використовується.
force_install_dir

за замовчуванням програми встановлюються в каталог ./SteamApps/common/<ім'я ігри>. Якщо ми хочемо встановити в інший, то вказуємо його як параметр цієї команди. Повинно бути зазначено до команди app_update.
app_update <appid> [-validate] [-language <lang>] [-beta <betaname>] [-betapassword <pwd>]

починає завантажувати (якщо ще не), або оновлювати існуючу інсталяцію програми. Необхідно вказівку appid. Можливо вказівку опції validate — в цьому випадку буде здійснюватися перевірка цілісності інсталяції і, при необхідності, додатково викачуватися відсутні або змінені файли. За фактом, аналогічно виконанню команди "Перевірити цілісність кешу..." в клієнт Steam, з тією різницею, що виконується для ігрового сервера. Очевидно, що суттєво сповільнює процес оновлення, і краще її вказувати вручну, коли виникає така необхідність, як ми це робили під час первісної інсталяції сервера.
app_set_config <appid> <key> <value>

вказує додаткові параметри для програми.
Докладніше по командам та змінним клієнта Steam можна почитати в рідній довідці, запустивши steamcmd.sh без параметрів. Працюють команди
help
,
find <підрядок>
.
Коли в процесі своєї життєдіяльності ігровий сервер отримує від майстер-серверів Steam інформацію про новому оновленні, він починає кожні п'ять хвилин канючити про необхідність перезапуску.
В консолі сервера:
^CMasterRequestRestart
Your server will be restarted on map change.
Your server will be restarted on map change.
Your server needs to be restarted in order to receive the latest update.
Your server needs to be restarted in order to receive the latest update.

І в логах:
L 07/08/2016 - 05:07:17: Your server will be restarted on map change.
L 07/08/2016 - 05:07:17: Your server needs to be restarted in order to receive the latest update.

При чергових змінах карт сервера завершать роботу, виконають команди з ~/cfg/tf2_update і, оновлені, запустяться заново. При цьому нічого страшного не відбудеться навіть в разі одночасної зміни карт і оновлення.
Одночасне оновлення серверів
Ну, може, крім підвищеної витрати трафіку.
У переважній більшості випадків достатньо використовувати цей режим оновлення. Але бувають варіанти, коли на одному із серверів карта змінюватися буде дуже нескоро, а то й зовсім не буде. Адже якщо спеціально не встановлювати критерії закінчення гри на даній карті, обмежуючи кількість раундів (змінна mp_maxrounds, за замовчуванням = 0), перемог (mp_winlimit = 0), фрагів (mp_fraglimit = 0), таймаут (mp_timelimit = 0), і так далі, то не буде зміни карти і, як наслідок, оновлення. Та й мало які карти й ігрові режими захочеться використовувати на тому ж другому сервері, і шкода втрачати нових гравців з-за того, що вони не можуть підключитися до нашого застарілого сервера.
Тоді на допомогу приходять інші варіанти.
Періодичне оновлення
Ми можемо зайти з іншого боку — регулярно по cron запускати steamcmd.sh з командами встановлення оновлень (так, "по-живому"), аналізувати результати і при успішне оновлення ініціювати перезапуск ігрових серверів.
Так, при запуску
~/Steam/steamcmd.sh +runscript ~/cfg/tf2_update
та при відсутності сервера оновлень, steamcmd.sh порадує нас повідомленням:
...
Connecting anonymously to Steam Public...Logged in OK
Waiting for license info...OK
Success! App '232250' already up to date.

При наявності оновлень, після автоматичного скачування і в разі успішної установки:
...
Update state (0x61) downloading, progress: 99.63 (3616706682 / 3630011517)
Update state (0x81) committing, progress: 100.00 (606937472 / 606937472)
Success! App '232250' fully installed.

на "fully installed" і будемо перевіряти. Реалізовуємо. Створюємо скрипт ~/update.sh:
update.sh
#!/bin/sh

~/Steam/steamcmd.sh +login anonymous +force_install_dir /home/game/tf2/ +app_update 232250 +quit > ~/steamcmd.log

if grep --quiet "fully installed" ~/steamcmd.log; then
# kill `cat /home/game/tf2/tf/srcds1.pid`
# ~/start1.sh &
# kill `cat /home/game/tf2/tf/srcds2.pid`
# ~/start2.sh &
fi

rm -f ~/steamcmd.log

Так, установку оновлень можна запускати, як вказуючи параметри командного рядка steamcmd.sh — "+login anonymous +force_install_dir ~/tf2/ +app_update 232250 +quit", так і з допомогою раніше створеного файлика tf2_update — "+runscript ~/cfg/tf2_update"
Скрипт мінімалістичний і жорстокий, тому в такому вигляді його використовувати не будемо. А ось після остаточної настройки запуску ігрових серверів, як у розділі "Автозапуск ігрових серверів", з використанням tmux скрипти запуску та налаштування sudo, можна заздалегідь попереджати користувачів про прийдешнє рестарті, так і виконувати його цивілізованіше. Тоді скрипт прийме більш прийнятний вигляд:
update.sh (v2)
#!/bin/sh

~/Steam/steamcmd.sh +login anonymous +force_install_dir /home/game/tf2/ +app_update 232250 +quit > ~/steamcmd.log

if grep --quiet "fully installed" ~/steamcmd.log; then
echo "Update installed"

tmux -L socket1 send-keys "say New update installed. Server will be restarted in 10 seconds. Please join us after a minute" Enter
tmux -L socket2 send-keys "say New update installed. Server will be restarted in 10 seconds. Please join us after a minute" Enter

sleep 10s

sudo /usr/bin/systemctl reload srcds1.service
sudo /usr/bin/systemctl reload srcds2.service
else
echo "Update not found"
fi

rm -f ~/steamcmd.log

Замість "say", якщо вже встановлений SourceMod його варіанти команд.
Такий варіант оновлення активуємо через наш файл crontab, не забуваючи зробити сам скрипт виконуваним:
$ chmod 744 ~/update.sh
$ crontab -e

Прописуємо запуск кожні півгодини:
crontab
*/30 * * * * ~/update.sh

Налаштування перенаправлення логів cron лог, доступний користувачеві game описано в розділі "Логи"
Тільки перевірка
У деяких випадках може знадобитися лише перевірити наявність оновлень, не встановлюючи їх прямо зараз.
У Valve є Steam Web API. Перевіряти наявність оновлень програм можна з використанням інтерфейсу ISteamApps/UpToDateCheck, наприклад, для самої гри Team Fortress 2 — http://api.steampowered.com/ISteamApps/UpToDateCheck/v1?appid=440&version=3528598, вказавши у параметрі version поточну версію гри (або просто якусь цифру). Але при виборі appid = 232250 (а, так само, як і для багатьох інших виділених серверів), видається помилка "couldn't get app info for the app specified.". На жаль.
Але, на щастя, саме для нашого Team Fortress 2 dedicated server є окремий інтерфейс — https://api.steampowered.com/IGCVersion_440/GetServerVersion/v1?format=json. При виконанні видається щось види:
{
"result": {
"success": true,
"deploy_version": 3531256,
"active_version": 3531256,
"min_allowed_version": 3528598
}
}

Формат виведеної інформації можна вказувати в рядку запиту — json, xml, vdf. Останній — Valve Data Format, пропрієтарний формат Valve, дуже схожий на json і легко в нього конвертований. Використовується у багатьох файлах — items_game.txt у Записах, в .acf, .vdf і так далі.
Взагалі, поля deploy_version і active_version використовуються Valve для відстеження версій, запущених на їх власних серверах, і вони не зобов'язані завжди збігатися з поточними публічними версіями. Але, з урахуванням цих ризиків, все ж можна спробувати використовувати цей api.
Дізнатися встановлену у нас версію сервера можна ввівши
version
в консолі сервера, або подивившись в ~/tf2/tf/steam.inf
Таким чином, при необхідності, можна періодично перевіряти актуальну версію сервера через Web API, порівнювати з встановленої у нас, ну а безпосередньо оновлення і рестарт ігрових серверів були описані вище. Наприклад так:
update.sh (v3)
#!/bin/sh

wget -q --no-check-certificate "https://api.steampowered.com/IGCVersion_440/GetServerVersion/v1?format=json" -O=~/GameVersion.json

VERSION_DEPLOYED=`grep deploy_version ~/GameVersion.json | sed -s 's/[^[:digit:]]//g"

VERSION_INSTALLED=`grep ServerVersion ~/tf2/tf/steam.inf | sed -s 's/[^[:digit:]]//g"

if [[ $VERSION_DEPLOYED -gt $VERSION_INSTALLED ]]; then
echo "New update is ready, $VERSION_DEPLOYED vs $VERSION_INSTALLED"
# Щось робимо

fi

Все, можна включати в crontab.
Справедливості заради, це далеко не єдині способи отримання інформації про оновлення. Крім того, що ще ховається в надрах Steam Web API, поточний білд нашого сервера можна подивитися в ~/tf2/steamapps/appmanifest_232250.acf, параметр "buildid". Актуальну версію можна запитати —
steamcmd.sh +login anonymous +app_info_update 1 +app_info_print 232250 +quit
, а там дивимося значення параметра "buildid" з шляху depots -> branches -> public (іноді app_info_print тупить, показує застарілу закешированную інформацію, не рятує навіть app_info_update 1. Тоді допоможе попереднє rm -f ~/Steam/appcache/appinfo.vdf). Автоматично отримувати номери білдів можна як ланцюжком з півдюжини grep, cut, tr та інших команд, з відомими допущеннями про структуру та порядок рядків, так і шляхом приведення вихідних даних до формату json (хоча б за допомогою sed + tr) з подальшим використанням стандартних інструментів.
Остаточний вибір способу оновлення буде зроблений у розділі "Автозапуск ігрових серверів".

Джерело: Хабрахабр
  • avatar
  • 0

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.