Параметри виділеного сервера Source під Linux, частина 3

  • Установка MetaMod і SourceMod
    • Установка MetaMod:Source
    • Установка SourceMod

  • Автозапуск ігрових серверів
  • Логи
    • Логи cron
    • Логи клієнта Steam

    • Журналів веб-сервера
    • Логи SourceMod
    • Логи ігрових серверів
    • Логи сервера статистики
  • Прив'язка до Steam і QuickPlay
    • Серверна обліковий запис
    • QuickPlay
Установка MetaMod і SourceMod
Прийшла пора внести свіжий струмінь у процес налаштування спільного співіснування наших серверів, а саме — додати MetaMod і SourceMod.
Установка MetaMod:Source
Спочатку встановимо плагін MetaMod:Source, який ніяких ігрових функцій не додає, а лише забезпечує інтерфейс між движком Source, грою та іншими плагінами.
Домашня сторінка http://www.metamodsource.net/
Завантажуємо останню версію і розпаковуємо архів.
$ wget http://cdn.probablyaserver.com/sourcemod/mmsource-1.10.6-linux.tar.gz
$ tar -xvzf mmsource-1.10.6-linux.tar.gz -C ~/tf2/tf

У каталозі ~/tf2/tf буде створено папку addons (до нього ми будемо встановлювати та інші моди), а в ньому каталог metamod з низкою файлів для різних Source ігор, в тому числі і для Team Fortress 2:
addons/
addons/metamod.vdf
...
addons/metamod/bin/metamod.2.tf2.so
addons/metamod/bin/server.so
...
addons/metamod/metaplugins.ini

Ігровий сервер srcds при запуску перевіряє наявність каталогу ~/tf2/tf/addons, шукає в ньому *.vdf файли, в яких параметр "file" повинні бути вказані шляху до бібліотек плагінів. В нашому випадку, як раз в такому файлі ~/tf2/tf/addons/metamod.vdf підключений плагін MetaMod:Source як "addons/metamod/bin/server" (шлях вказується щодо ~/tf2/tf/).
Тепер ми встановимо SourceMod і підключимо його до MetaMod.
Установка SourceMod
Домашня сторінка http://www.sourcemod.net/
Переходимо на http://www.sourcemod.net/downloads.php?branch=stable, завантажуємо останню версію під Linux і розпаковуємо архів
$ wget https://sm.alliedmods.net/smdrop/1.8/sourcemod-1.8.0-git5947-linux.tar.gz
$ tar -xvzf sourcemod-1.8.0-git5947-linux.tar.gz -C ~/tf2/tf

~/tf2/tf/addons з'явився каталог sourcemod, в ~/tf2/tf/cfg/ — каталог sourcemod з файлами конфігурації, а в
~/tf2/tf/addons/metamod — файлик sourcemod.vdf.
addons/metamod/sourcemod.vdf
addons/sourcemod/
addons/sourcemod/scripting/
addons/sourcemod/configs/core.cfg
...
cfg/sourcemod/sm_warmode_off.cfg
cfg/sourcemod/sm_warmode_on.cfg
cfg/sourcemod/sourcemod.cfg

Так як одна інсталяція SourceMod не одночасно обслуговувати декілька серверів, то нам необхідно розтиражувати по кількості серверів. В каталозі addons перейменовуємо sourcemod в sourcemod1 і копіюємо з усім вмістом в sourcemod2, попередньо для зручності виконавши dos2unix для файлів налаштувань:
$ mv ~/tf2/tf/addons/sourcemod ~/tf2/tf/addons/sourcemod1
$ cd ~/tf2/tf/addons/sourcemod1/configs
$ dos2unix *.cfg *.ini *.txt
$ cp -r ~/tf2/tf/addons/sourcemod1 ~/tf2/tf/addons/sourcemod2

MetaMod знаходить і підключає SourceMod завдяки файлу addons/metamod/sourcemod.vdf. Але цей файл один, а нам треба два різних, для кожного сервера. У MetaMod є параметр, що вказує на каталог (не файл!) з конфігурацією, тому створимо два каталогу cfg1 і cfg2 і помістимо туди sourcemod.vdf, який і будемо правити.
$ mkdir ~/tf2/tf/addons/metamod/cfg{1,2}
$ dos2unix ~/tf2/tf/addons/metamod/sourcemod.vdf
$ mv ~/tf2/tf/addons/metamod/sourcemod.vdf ~/tf2/tf/addons/metamod/cfg1/sourcemod.vdf
$ cp ~/tf2/tf/addons/metamod/cfg1/sourcemod.vdf ~/tf2/tf/addons/metamod/cfg2/sourcemod.vdf

Редагуємо файли, виправляючи шляху до інсталяціям SourceMod (так само, відносно ~/tf2/tf):
~/tf2/tf/addons/metamod/cfg1/sourcemod.vdf:
cfg1/sourcemod.vdf
"Metamod Plugin"
{
"alias" "sourcemod"
"file" "addons/sourcemod1/bin/sourcemod_mm"
}

~/tf2/tf/addons/metamod/cfg2/sourcemod.vdf (виправляємо 1 -> 2):
cfg2/sourcemod.vdf
"Metamod Plugin"
{
"alias" "sourcemod"
"file" "addons/sourcemod2/bin/sourcemod_mm"
}

Для зручності робимо символьні посилання на каталоги з налаштуваннями і логами:
$ ln -s ~/tf2/tf/addons/metamod/cfg1 ~/cfg/mm1
$ ln -s ~/tf2/tf/addons/metamod/cfg2 ~/cfg/mm2
$ ln -s ~/tf2/tf/addons/sourcemod1/configs ~/cfg/sm1
$ ln -s ~/tf2/tf/addons/sourcemod2/configs ~/cfg/sm2
$ ln -s ~/tf2/tf/addons/sourcemod1/logs ~/log/sm1
$ ln -s ~/tf2/tf/addons/sourcemod2/logs ~/log/sm2

Якихось окремих команд для запуску MetaMod прописувати не треба — ігровий сервер запустить його автоматично, але нам треба вказати різні каталоги для завантаження SourceMod.
У файлі ~/cfg/autoexec1.cfg для першого сервера дописуємо в кінець:
autoexec1.cfg
//...

// Load SourceMod instance No 1
mm_basedir addons/metamod/cfg1

Для другого сервера в ~/cfg/autoexec2.cfg аналогічно, тільки замість "cfg1" -> "cfg2":
autoexec2.cfg
//...

// Load SourceMod instance No 2
mm_basedir addons/metamod/cfg2

Тепер MetaMod знає звідки завантажувати SourceMod, але останній не знає звідки йому брати свої налаштування. Пропишемо шляху для кожного SourceMod. На відміну від MetaMod, параметри нам доведеться вказувати аж у командному рядку запуску сервера. Ні в autoexec.cfg, ні в server.cfg вони не спрацьовують.
В скриптах запусках start1.sh і start2.sh у CMDLINE дописуємо:
start1.sh
CMDLINE="...
+sm_basepath addons/sourcemod1 +sm_corecfgfile addons/sourcemod1/configs/core.cfg \
...

Це для першого сервера. Для другого сервера аналогічно, тільки замість "sourcemod1" -> "sourcemod2":
start2.sh
CMDLINE="...
+sm_basepath addons/sourcemod2 +sm_corecfgfile addons/sourcemod2/configs/core.cfg \
...

Параметр sm_corecfgfile необхідний, так як шлях до core.cfg не береться sm_basepath, що логічно було б припустити.
Для перевірки можна запустити перший ігровий сервер і коли він повністю запуститься, в його консолі ввести (команди виділені кутовими дужками):
>>> meta version
Metamod:Source version 1.10.6
Built from: https://github.com/alliedmodders/metamod-source/commit/9fed12f
Build ID: 946:9fed12f
Loaded As: Valve Server Plugin
Compiled on: Sep 12 2015
Plugin interface version: 15:14
SourceHook version: 5:5
http://www.metamodsource.net/
>>> mm_basedir
"mm_basedir" = "addons/metamod/cfg1" ( def. "addons/metamod" )
singleplayer
- Metamod:Source Folder Base
>>> meta list
Listing 4 plugins:
[01] SourceMod (1.8.0.5907) by AlliedModders LLC
[02] TF2 Tools (1.8.0.5907) by AlliedModders LLC
[03] SDK Hooks (1.8.0.5907) by AlliedModders LLC
[04] SDK Tools (1.8.0.5907) by AlliedModders LLC
>>> meta info 1
Plugin 1 is running.
Name: "SourceMod" by AlliedModders LLC
Версія: 1.8.0.5907
Description: Extensible administration and scripting system
License: See LICENSE.txt
URL: http://www.sourcemod.net/
Details: API 015, Date: Apr 26 2016
File: /home/game/tf2/tf/addons/sourcemod1/bin/sourcemod_mm_i486.so

>>> sm_basepath
"sm_basepath" = "addons/sourcemod1" ( def. "addons/sourcemod" )
- SourceMod base path (set via command line)
>>> sm_corecfgfile
"sm_corecfgfile" = "addons/sourcemod1/configs/core.cfg" ( def. "addons/sourcemod/configs/core.cfg" )
- SourceMod core configuration file
>>> sm plugins list
[SM] Listing 17 plugins:
01 "Admin Menu" (1.8.0.5907) by AlliedModders LLC
...
17 "Player Commands" (1.8.0.5907) by AlliedModders LLC
>>> sm exts list
[SM] Displaying 9 extensions:
[01] Automatic Updater (1.8.0.5907): Updates SourceMod gamedata files
...
[09] SQLite (1.8.0.5907): SQLite Driver

Ну що ж, всі шляхи до каталогів і файлів вірні, сімнадцять стандартних плагінів і дев'ять розширень запущені. Пізніше ми розберемо хто що робить, а поки продовжимо.
Якщо ж при введенні команд видаються помилки виду:
>>> meta list
Listing 1 plugin:
[01] <FAILED>
>>> sm_basepath
Unknown command "sm_basepath"

То значить MetaMod не зміг завантажити SourceMod. Треба шукати в чому справа.
Перелік консольних команд MetaMod:Source — Console Commands (SourceMM)
Розширення знаходяться у каталозі ~/tf2/tf/addons/sourcemod{1,2}/extensions — для всіх підтримуваних ігор на движку Source, не тільки TF2.
Скомпільовані модулі знаходяться в каталозі ~/tf2/tf/addons/sourcemod{1,2}/plugins. Якщо потрібно відключити який-небудь плагін, то його можна просто перенести в підкаталог disabled. Самі вихідні тексти плагінів знаходяться каталозі ~/tf2/tf/addons/sourcemod{1,2}/scripting. Там же є компілятор і скрипт compile.sh, який компілює код і поміщає скомпільовані плагіни в підкаталог compiled, звідки їх можна перенести в ~/tf2/tf/addons/sourcemod{1.2}/plugins — і вони стануть доступні для використання SourceMod.
Тепер можна налаштувати SourceMod для кожного сервера, редагуючи файли core.cfg в ~/tf2/tf/addons/sourcemod{1,2}/configs. У нашому випадку задовольняє параметрами за замовчуванням. Зверніть увагу, що при цьому параметром "DisableAutoUpdate No" включено автооновлення ігрових даних SourceMod в каталогах ~/tf2/tf/addons/sourcemod{1,2}/gamedata.
Так само можна core.cfg встановити параметр "LogMode" значення "game" — тоді логи записуватимуться не окремі файли, а в логи ігрового сервера. Детальніше у розділі "Логи"
Інші файли конфігурації розберемо пізніше.
Однак є ще один файл конфігурації — ~/tf2/tf/cfg/sourcemod/sourcemod.cfg — він виконується при кожній зміні карт слідом за server.cfg і є загальним для всіх інсталяцій SourceMod. Тому залишаємо в sourcemod.cfg лише команди, загальні для обох серверів, а індивідуальні переносимо в окремі файли для кожного сервера.
$ dos2unix ~/tf2/tf/cfg/sourcemod/sourcemod.cfg
$ cp ~/tf2/tf/cfg/sourcemod/sourcemod.cfg ~/cfg/sourcemod_default.cfg
$ ln -s ~/tf2/tf/cfg/sourcemod ~/cfg/sm

Редагуємо ~/tf2/tf/cfg/sourcemod/sourcemod.cfg, традиційно додаємо висновок "echo", виправляємо "sm_show_activity" і встановлюємо у "sm_datetime_format" звичний формат виведення дати/часу.
sourcemod.cfg
echo "*** ~/tf2/tf/cfg/sourcemod/sourcemod.cfg"
// SourceMod Configuration File
// This file is automatically executed by SourceMod every mapchange.

// Specifies how admin activity should be relayed to users.
sm_show_activity 28

// Default datetime formatting rules when displaying to clients.
sm_datetime_format "%d %b %Y - %H:%M:%S"

Все. Інше видаляємо. Пізніше, коли захочеться встановити для серверів свої параметри, то можна взяти їх з збереженого ~/cfg/sourcemod_default.cfg і вказати в якомусь файлі конфігурації сервера. Чому не можна залишити все як є — в оригінальному sourcemod.cfg? А тому що він виконується при кожній зміні карт слідом за server{1,2}.cfg — тобто будь-які установки, наприклад, що стосуються резервних слотів, прописані в server{1,2}.cfg будуть перезаписані значеннями за замовчуванням з цього файлу. А ті ж резервні слоти ми будемо налаштовувати для наших серверів по-різному.
При установці нових плагінів SourceMod, файли конфігурації можуть автоматично створюватися в ~/tf2/tf/cfg/sourcemod/ і ставати загальними для обох інсталяцій SourceMod. Власне, там вже лежить файл з налаштуваннями для плагіна funcommands.smx
Так само SourceMod за замовчуванням періодично завантажує зі свого сервера (update.sourcemod.net оновлення файлів з ігровими даними, що знайде своє відображення в логах. На прикладі першого сервера (~/tf2/tf/addons/sourcemod1/logs/), рядки 3,4,5:
L 03/21/2014 - 14:52:41: SourceMod log file session started (file "L20140321.log") (Version "1.5.3")
L 03/21/2014 - 14:52:41: -------- Mapchange to cp_well --------
L 03/21/2014 - 14:52:56: [UPDATER] Successfully updated gamedata file "sdkhooks.games/engine.csgo.txt"
L 03/21/2014 - 14:52:56: [UPDATER] Successfully updated gamedata file "sdktools.games/engine.csgo.txt"
L 03/21/2014 - 14:52:56: [UPDATER] Successfully updated gamedata file "sm-cstrike.games/game.csgo.txt"
L 03/21/2014 - 14:52:56: [UPDATER] SourceMod has been updated, please reload it or restart your server.
L 03/21/2014 - 14:55:26: SourceMod log file session started (file "L20140321.log") (Version "1.5.3")
L 03/21/2014 - 14:55:26: -------- Mapchange to cp_well --------

Документація по SourceMod — налаштування, управління, невеликий FAQ (eng).
Так як чергові оновлення Team Fortress 2 можуть порушувати крихке взаємодія ігри і SourceMod, то має сенс відслідковувати нові версії і білди і регулярно оновлюватися.
Продовження з описом установки плагінів та інтерактивним взаємодією гравців з сервером описано в розділі "Плагіни SourceMod", а поки рушимо далі — до налаштування запуску серверів.
Автозапуск ігрових серверів
Наші ігрові сервера вже досить дорослі для того, щоб можна було їх включати в автозапуск. Для систем з System V init можна переробити раніше створені скрипти запуску, або використовувати приклади з TF2 Wiki. Для систем з systemd, як у нас, робимо два файлу служб, невигадливо іменованих srcds1.service і srcds2.service.
Довідково, для освіження матеріалу: Після всіх додатків (Записи, SourceMod), скрипт запуску того ж першого сервера ~/start1.sh у повній комплектації повинен був виглядати якось так:
start1.sh
#!/bin/sh
#
# Запуск першого сервера.

# Шлях до каталогу з грою, де лежить файл srcds_run
GAMEFOLDER=/home/game/tf2

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

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

Ми вже звикли до скрипта srcds_run, тому будемо і далі використовувати його. Треба лише потурбуватися автоматичним перезапуском ігрового серевера при виконанні команд
quit
,
_restart
. Зараз скрипт перезапускає сервер тільки якщо він закінчився аварійно з ненульовим кодом виходу, або з нульовим при включеному автообновлении.
кілька Варіантів. Перший — можна просто включити стандартне оновлення (секція "Автоматичне" у розділі "Оновлення серверів"). Другий — створити копію скрипта з іншим ім'ям і поправити його на предмет вічного перезапуску сервера (вихідний скрипт правити не варто — він може замінитися при оновленні) і використовувати його в подальшому. Третій — якщо планується оновлювати сервера самостійно, то можна включити автооновлення, додавши -autoupdate і два його параметра-сателіта в командний рядок запуску, але в якості скрипта автооновлення використовувати файлик типу ~/cfg/tf2_quit, що складається лише з одного рядка з командою quit, тобто фактично, оновлення не будуть перевірятися.
Знання примножують печалі. Але вибір за вами. У нашому ж випадку, для першого сервера ми у файлах конфігурації ще не прописували критерії закінчення раундів, а другий сервер взагалі буде з нестандартними картами, цілком можливо, що і з нескінченними раундами, тому в автозапуску будемо використовувати третій варіант — з фіктивним автообновлением, а справжнє оновлення — через регулярний запуск update.sh скрипта в crontab. Знову ж таки, так цікавіше.
Отже, файли служб. Для зручності ми будемо використовувати термінальний мультиплексор tmux (бажаючі можуть використовувати замість нього screen), який буде запускати скрипт srcds_run. Параметри командного рядка перейшли практично незмінними з запуску скриптів, які ми використовували до цього.
Так як ігрові сервера виконуються від імені користувача game, то по-доброму, можна було б створювати файли запуску в користувальницькому оточенні, в ~/.config/systemd/user/. Але даний розділ документації тестувався на centos 7, де запуск systemd в режимі користувача не функціонує, тому файли служб ми створюємо від імені root.
Заходимо як root, створюємо файл /etc/systemd/system/srcds1.service для першого сервера.
srcds1.service
# /etc/systemd/system/srcds1.service
#
# Team Fortress 2 Source Dedicated Server

[Unit]
Description=Team Fortress 2 Source Dedicated Server No 1
After=network.target

[Service]
User=game
Group=game
WorkingDirectory=/home/game/Steam
Type=oneshot
RemainAfterExit=yes
PIDFile=/home/game/tf2/tf/srcds1.pid
ExecStart=/usr/bin/tmux -L socket1 new-session -d '/home/game/tf2/srcds_run \
+sv_pure 2 -game tf +maxplayers 24 \
-pidfile /home/game/tf2/tf/srcds1.pid \
-ugcpath /home/game/tf2/steamapps/workshop1 \
-replay replay1.cfg -replayserverdir server1 \
+exec autoexec1.cfg +servercfgfile server1.cfg \
-port 27015 -steamport 26900 +clientport 27005 +tv_port 27020 -strictportbind \
-autoupdate -steam_dir /home/game/Steam -steamcmd_script /home/game/cfg/tf2_quit \
+sm_basepath addons/sourcemod1 +sm_corecfgfile addons/sourcemod1/configs/core.cfg'

ExecStop=/usr/bin/tmux -L socket1 send-keys "quit" Enter ; /usr/bin/sleep 5s ; /usr/bin/tmux -L socket1 kill-session
ExecReload=/usr/bin/tmux -L socket1 send-keys "_restart" Enter
ExecStopPost=/usr/bin/rm -f /home/game/tf2/tf/srcds1.pid

[Install]
WantedBy=multi-user.target

Невелике пояснення за параметрами ExecStop і ExecReload. Для завершення роботи сервера ми надсилаємо йому промені любові і команду
quit
в консоль, чекаємо кілька секунд для завершення роботи, і, поки все не запустилося заново, прибиваємо сесію. Схожий механізм для рестарту сервера. При бажанні можна додати висновок попередження гравцям про прийдешнє рестарті — як це було в прикладі одного з скриптів для оновлення, у відповідному розділі.
Копіюємо srcds1.service в srcds2.service, коригуємо шляхи, порти і ім'я tmux сокета. Зберігаємо. /etc/systemd/system/srcds2.service:
srcds2.service
# /etc/systemd/system/srcds2.service
#
# Team Fortress 2 Source Dedicated Server

[Unit]
Description=Team Fortress 2 Source Dedicated Server No 2
After=network.target

[Service]
User=game
Group=game
WorkingDirectory=/home/game/Steam
Type=oneshot
RemainAfterExit=yes
PIDFile=/home/game/tf2/tf/srcds2.pid
ExecStart=/usr/bin/tmux -L socket2 new-session -d '/home/game/tf2/srcds_run \
+sv_pure 2 -game tf +maxplayers 24 \
-pidfile /home/game/tf2/tf/srcds2.pid \
-ugcpath /home/game/tf2/steamapps/workshop2 \
-replay replay2.cfg -replayserverdir server2 \
+exec autoexec2.cfg +servercfgfile server2.cfg \
-port 27016 -steamport 26901 +clientport 27006 +tv_port 27021 -strictportbind \
-autoupdate -steam_dir /home/game/Steam -steamcmd_script /home/game/cfg/tf2_quit \
+sm_basepath addons/sourcemod2 +sm_corecfgfile addons/sourcemod2/configs/core.cfg'

ExecStop=/usr/bin/tmux -L socket2 send-keys "quit" Enter ; /usr/bin/sleep 5s ; /usr/bin/tmux -L socket2 kill-session
ExecReload=/usr/bin/tmux -L socket2 send-keys "_restart" Enter
ExecStopPost=/usr/bin/rm -f /home/game/tf2/tf/srcds2.pid

[Install]
WantedBy=multi-user.target

Тут ми спеціально запускаємо дві окремі копії tmux, кожну для свого ігрового сервера. Можна було б, звичайно, обійтися сесіями всередині одного tmux (tmux new-session -d -s tf1 і tmux new-session -d -s tf2), але тоді це стало б додатковою точкою для epic fail — коли ненавмисний Ctrl-C прибив би всі наші сервера.
Не забуваємо створити файлик ~/cfg/tf2_quit з вмістом:
tf2_quit
quit

Перевіряємо, що обидва .service файлу доступні на запис тільки для root, потім запускаємо, включаємо:
# systemctl start srcds1
# systemctl start srcds2
# systemctl enable srcds1
# systemctl enable srcds2

Але зараз у нас дурна ситуація — ігрові сервера стартують при запуску нашого сервера, але користувач game не може ними керувати стандартними способами з допомогою systemctl (start, stop, reload), хоча цілком може ними "керувати" за допомогою Ctrl+C tmux сесії, з подальшим запуском вручну. Виправляємо несправедливість.
Поки ми ще root, запускаємо
visudo
, коригуємо файл sudoers, дописавши в кінець:
sudoers
Defaults:game !requiretty
game ALL= NOPASSWD: /usr/bin/systemctl start srcds1.service, /usr/bin/systemctl start srcds2.service
game ALL= NOPASSWD: /usr/bin/systemctl stop srcds1.service, /usr/bin/systemctl stop srcds2.service
game ALL= NOPASSWD: /usr/bin/systemctl reload srcds1.service, /usr/bin/systemctl reload srcds2.service
game ALL= NOPASSWD: /usr/bin/systemctl status srcds1.service, /usr/bin/systemctl status srcds2.service
game ALL= NOPASSWD: /usr/bin/systemctl enable srcds1.service, /usr/bin/systemctl enable srcds2.service
game ALL= NOPASSWD: /usr/bin/systemctl disable srcds1.service, /usr/bin/systemctl disable srcds2.service

Тут ми користувачеві game надаємо можливість за допомогою sudo, без запиту пароля (якого у нього і немає) виконувати команди start, stop, reload, status і для купи enable з disable для першого і другого сервера. А параметр "Defaults:game !requiretty" дозволить нам запускати sudo з файлу crontab. За бажанням можна додати дозвіл на використання інших команд типу is-* та інших.
Права на команди виду
systemctl edit [--full]
ми надавати не будемо. Все-таки безпека повинна бути… безпечною.
Виходимо з-під root, перевіряємо з-під game:
$ sudo -l

Matching Defaults entries for game on this host:
...
..., !requiretty

User may run game the following commands on this host:
(root) NOPASSWD: /usr/bin/systemctl start srcds1.service, root /usr/bin/systemctl start srcds2.service
(root) NOPASSWD: /usr/bin/systemctl stop srcds1.service, root /usr/bin/systemctl stop srcds2.service
(root) NOPASSWD: /usr/bin/systemctl reload srcds1.service, root /usr/bin/systemctl reload srcds2.service
(root) NOPASSWD: /usr/bin/systemctl status srcds1.service, root /usr/bin/systemctl status srcds2.service
(root) NOPASSWD: /usr/bin/systemctl enable srcds1.service, root /usr/bin/systemctl enable srcds2.service
(root) NOPASSWD: /usr/bin/systemctl disable srcds1.service, root /usr/bin/systemctl disable srcds2.service

Можна тут же запустити
sudo systemctl status srcds1.service
, потестувати.
Команди необхідно буде вводити без скорочення параметрів. Тобто sudo systemctl status srcds1.service — норм, а от sudo systemctl status srcds1 — вже не торт.
Якщо при маніпуляціях з ігровими серверами за допомогою systemctl видається помилка виду "Failed to stop srcds1.service: Interactive authentication required." — то значить ви забули про sudo :-)
Коли все запрацює, можна буде працювати з консолями серверів вже як користувач game, підключаючись через tmux:
$ tmux -L socket1 attach
$ tmux -L socket2 attach

Відключатися від tmux сесії — Ctrl+b, d.
Можна прописати аліаси в ~/.bash_profile:
.bash_profile
alias tf1="tmux -L socket1 attach"
alias tf2="tmux -L socket2 attach"

За замовчуванням, розмір збереженої історії для tmux становить 2000 рядків, але його можна збільшити, наприклад до 10000 рядків, створивши файл ~/.tmux.conf виду:
.tmux.conf
set-option -g history-limit 10000
set-option -g set-remain-on-on exit

Друга команда не закриває tmux сесію при завершенні основної програми, що дає можливість почитати її останнє пробач в консолі.
Переміщатися по історії — Ctrl+b [, а далі звичайними клавішами — Up/Down, PgUp/PgDown. Вихід з цього режиму — q.
Логи
Логів у нас буде багато і різних. А саме:
Логи cron
У нас через cron запускаються скрипти перевірки оновлень, сервера статистики HLstatsX, видалення застарілих Записів, а їх висновок відображається в /var/log/cron у вигляді
Jun 15 12:55:01 server CROND[584]: (game) CMD (cd $HOME/stat/scripts && ./run_hlstats start 2 27500 1)
Jun 15 12:55:01 server CROND[583]: (game) CMDOUT (HLstatsX:CE daemon control)
Jun 15 12:55:01 server CROND[583]: (game) CMDOUT (http://www.hlxce.com)
Jun 15 12:55:01 server CROND[583]: (game) CMDOUT (---------------------------)
Jun 15 12:55:01 server CROND[583]: (game) CMDOUT (Daemon is already running on port 27500)
Jun 15 12:55:01 server CROND[583]: (game) CMDOUT (Daemon is already running on port 27501)
...

Так як /var/log/cron ніхто прочитати не зможе окрім користувача root, а йому це не цікаво, то хотілося б дати користувачеві доступ game до логів його crontab файлу. Звичайно, можна для кожного сценарію в кінці рядка запуску дописати щось види "… >> $HOME/log/cron.log" але ці "логи" будуть без міток часу, та й взагалі, кустарщина. Більш культурний варінт "… | /usr/bin/logger --tag srcds" нічого не змінює — ну повідомлення будуть потрапляти не в /var/log/cron, а в /var/log/messages, різниці.
Тому ми у налаштуваннях демона rsyslog зробимо так, що повідомлення від cron, що починаються з імені користувача "(game)", перенаправляються у файл /home/game/log/cron.log, власником якого є користувач game, і не потрапляють в подальшу обробку (в "cron.* /var/log/cron")
У нас встановлений rsyslogd версії 8.19, і в /etc/rsyslog.conf директиву
$IncludeConfig /etc/rsyslog.d/*.conf
знаходиться до правила
cron.* /var/log/cron
, тому перехоплювати повідомлення від наших скриптів будемо, створивши як користувач root файл /etc/rsyslog.d/srcds-10-cron.conf з вмістом:
srcds-10-cron.conf
# /etc/rsyslog.d/srcds-10-cron.conf

if $syslogfacility-text == "крок" and $msg startswith " (game)" then {
action(
type = "omfile"
fileOwner = "game"
fileGroup = "game"
file = "/home/game/log/cron.log"
)
stop
}

Детальніше про використані командах — omfile, properties.
Перевіряємо синтаксис, якщо все ок, то перезапускаємо демона і насолоджуємося свіжоствореному логом.
# rsyslogd -N 2
# systemctl restart rsyslog

Поки ми ще root, налаштовуємо ротацію логів, створивши файл /etc/logrotate.d/srcds-cron:
srcds-cron
#/etc/logrotate.d/srcds-cron

/home/game/log/cron.log {
su game game
daily
dateext
maxage 3
missingok
copytruncate
compress
notifempty
}

Перевіряємо:
# logrotate --debug --force /etc/logrotate.d/srcds-cron

Логи клієнта Steam
Ці логи знаходяться в ~/Steam/logs/. Ротація відбувається автоматично, силами самого клієнта. Поточний лог перейменовується в
*.previous.txt
,
*.previous.txt
попередньо видаляється. Спеціально ми їх обробляти не будемо, якийсь необхідності зберігати історичні дані немає — поточні проблеми з підключенням можна подивитися в активних логах, а що було з коннектом до серверів Valve дев'ятого термідора другого року — nobody cares...
Журналів веб-сервера
У нас з ігровими серверами співпрацюють три віртуальних веб-серверів, обслуговуючих:
  • Fast Download, логи в /var/www/fastdl.example.org/log/
  • Записи (Replay), логи в /var/www/replay.example.org/log/
  • HLstatsX, логи в /var/www/stat.example.org/log/
Ротація цих логів у нас налаштована в /etc/logrotate.d/srcds-nginx, передбачається, що логи з помилками будемо переглядати самостійно, а логи доступу можна згодовувати хоч Elasticsearch, Kibana і Logstash — але опис ELK стека поза обсягу даного проекту.
Логи SourceMod
Ці логи знаходяться в каталогах ~/tf2/tf/addons/sourcemod{1,2}/logs. Їх налаштування прописані у відповідних ~/tf2/tf/addons/sourcemod{1,2}/configs/core.cfg:
Logging on

логи вкл/викл
LogMode daily

ротація логів — щоденна (daily), при зміні карти (map), і третій режим (game) — писати в логи ігрового сервера.
DebugSpew no

деталізувати в логах оновлення ігрових даних
Логи SourceMod ведуться досить скромно, тому досить налаштувати їх регулярну ротацію, або не морочитися і просто в core.cfg прописати
LogMode game
, тоді вони гармонійно впишуться в логи ігрових серверів, як-то так:
L 06/20/2016 - 04:53:24: Executing dedicated server config file server1.cfg
L 06/20/2016 - 04:53:32: server_cvar: "sv_tags" "HLstatsX:CE,cp,increased_maxplayers"
L 06/20/2016 - 04:53:32: tf_server_identity_account_id not set; not logging into account registered
L 06/20/2016 - 04:53:32: server_cvar: "sv_contact" "game@example.org"
L 06/20/2016 - 04:53:33: [UPDATER] Successfully updated gamedata file "core.games/common.games.txt"
L 06/20/2016 - 04:53:33: [UPDATER] Successfully updated gamedata file "sdkhooks.games/game.doi.txt"
L 06/20/2016 - 04:53:33: [UPDATER] Successfully updated gamedata file "sdkhooks.games/master.games.txt"
L 06/20/2016 - 04:53:33: [UPDATER] Successfully updated gamedata file "sdktools.games/game.doi.txt"
L 06/20/2016 - 04:53:33: [UPDATER] Successfully updated gamedata file "sdktools.games/master.games.txt"
L 06/20/2016 - 04:53:33: [UPDATER] SourceMod has been updated, please reload it or restart your server.
L 06/20/2016 - 04:53:33: Connection to Steam servers successful.
L 06/20/2016 - 04:53:33: Public IP is 192.0.2.0.
L 06/20/2016 - 04:53:33: Assigned anonymous gameserver Steam ID [A:1:123456789:1234].
L 06/20/2016 - 04:53:33: VAC secure mode is activated.
L 06/20/2016 - 04:53:34: server_cvar: "sm_nextmap" "cp_well"

Логи ігрових серверів
Логи ігрових серверів знаходяться в ~/log/server{1,2}/. Мінімальну налаштування логів ми провели при написанні конфігураційних файлів, але зараз розглянемо значення деяких змінних детальніше:
log off

глобально вмикає (on) ведення логів даного ігрового сервера. Логи можуть направлятися в файл (sv_logfile), на консоль сервера (sv_logecho), транслюватися по UDP (logaddress_add).
sv_logfile 1

включає запис логів у файл (1), при цьому потрібно включення попередньою командою. Каталог для логів і формат імені файлу задаються параметрами sv_logsdir і sv_logfilename_format.
sv_logsdir logs

каталог для логів. За замовчуванням, був би ~/tf2/tf/logs, але так як ми логи наших двох серверів розводимо за різними каталогами, каталоги /home/game/log/server1 і /home/game/log/server2 відповідно. Хоча, звичайно, можна було б писати в один каталог, але з різним іменуванням файлів.
sv_log_onefile 0

вести запис логів в один файл (1), або при зміні карти створювати новий (0), наприклад: l0618000.log -> l0618001.log -> l0618002.log… l0619000.log -> l0619001.log і так далі. Відзначимо дві особливості при включенні цього параметра: по-перше, при настанні нових доби автоматичної ротації лода l0618000.log -> l0619000.log не відбудеться; по-друге, якщо в консолі або за допомогою якого-небудь файлу конфігурації зробити log off і тут же log on, то запис почнеться в новий файл, з инкрементированным номером.
sv_logfilecompress 0

при початку запису в новий файл логів, старий буде стискатися gzip і перейменовуватися в
<ім'я_файла_журналу>.log.gz
. Задумка хороша, реалізація під Linux кульгає. Так, при встановленні цієї змінної в "1" і зміни карти (що, при нашому sv_log_onefile = "0" викликає запис логів в новий файл), на консолі сервера з'являється лайка, створюється порожній .gz файл, а старий файл лода не видаляється. А все через регістра першого символу імені файлу — "l" проти "L", що принципово в Linux:
---- Host_Changelevel ----
Compressing /home/game/log/server2/L0713019.log to /home/game/log/server2/L0713019000.log.gz...
Success. Removing /home/game/log/server2/L0713019.log.
Unable to remove /home/game/log/server2/L0713019.log!
Unable to remove /home/game/log/server2/L0713019.log!
Server data logging to file /home/game/log/server2/L0713020.log
Applying new item schema, version 5C0BC93D

sv_logfilename_format ""

формат іменування файлів з логами. Повинен зазначатися до параметра "log on". Якщо спеціально не вказувати, то файли з логами зараз іменуються як
l<Місяць><День><000...999>.log
, де перший символ
<Latin Small Letter L>
, а останнім тризначне число в імені инкрементируется для кожного нового лода, в межах поточних діб. Можна задавати свій формат, з використанням параметрів функції strftime. Тобто, при вказівці "sv_logfilename_format %Y — %m — %d" файл буде виглядати як "20160714.log". Автонумерація в цьому випадку буде види 20160714.log -> 20160714_000.log -> 20160714_001.log і так далі. Забавно, але при явній встановленні формату, починає працювати параметр sv_logfilecompress — попередній файл лода дійсно архівується.
log_verbose_enable 0

включає (1) докладне ведення логів. Так, кожні кілька секунд (визначається log_verbose_interval) туди пишуться поточні тривимірні координати гравців. Лог розростається неймовірно. Включати, мабуть, має сенс хіба що для побудови теплових карт рухи гравців, з селекцією за класами. Щось на зразок http://geit.uk/blog/player-flow/.
log_verbose_interval 3.0

задає інтервал запису докладного лода. За замовчуванням — кожні 3 секунди.
sv_rcon_log 1

при відключенні (0), не виводить на консоль і в лог надходять rcon команди (результати виконання команд виводяться на консоль раніше). Так як в нашій конфігурації rcon використовує виключно HLstatsX, то економія в частині розмірів логів невелика, але все ж спаму на консолі сервера буде поменше, без ось цього:
rcon from "192.0.2.0:60533": command "status"
rcon from "192.0.2.0:60533": command "hlx_sm_psay "30" 2 "Round Over - All actions/frags are ignored <...>
rcon from "192.0.2.0:60533": command "hlx_sm_psay "30" 1 "Red got 10 points for Round Win""
rcon from "192.0.2.0:60533": command "hlx_sm_psay "30" 1 "Asuka got 2 points (1,025) for Kill Assist""

sv_logecho 1

дублює висновок лода на консоль. Природно, відключаємо (0).
sv_logbans 0

при включенні (1) фіксує інформацію про бані гравця в лог:
L 07/13/2016 - 23:09:31: Addip: "<><><>" was banned by IP "for 10.00 minutes" by "Console" (IP "10.1.1.1")

logaddress_add

вказує адресу: порт, куди транслюватимуться логи по UDP, в нашому випадку для HLstatsX. Першого сервера ми встановлювали 192.0.2.0:27500, другого — 192.0.2.0:27501
logaddress_del

видаляє адреса: порт з трансляції.
logaddress_delall

видаляє всі адреси з трансляції
developer 0

забезпечує більш докладний вивід інформації на консоль сервера. Варіанти значень — 0 (за замовчуванням), 1, 2, 3...
Ось логи ігрових серверів має сенс зберігати деякий час, на випадок скарг на того чи іншого гравця — мат в чаті, образа інших гравців, двісті вісімдесят друга стаття і так далі.
Зазвичай логи сервера при повному завантаженні та інтенсивної двіжусі ростуть на 3.5 — 4.0 тис. рядків у годину, близько 0.5 — 0.6 Мб.
Запис логів ведеться таким способом, що якщо запускати ротацію логів з допомогою logrotate без параметра copytruncate у файлі налаштувань, то після неї нових логів ми не побачимо до зміни карти (і то, при sv_log_onefile 0). Запуск з параметром copytruncate призводить до обрізання старого лода посередині рядка (як пощастить, так як ігрові сервера, якщо не включати sv_logflush 1, буферизируют запис логів в файл, причому не по рядках, а покілобайтна) і бінарним сміття на початку нового файлу, та так, що вже при його ротації, архів складається з одного рядка "Binary file (standard input) matches".
з Огляду на це, роботу з логами серверів можна організувати наступними способами:
  1. Дуже ледачий. Нічого не робити. При наявності інстинкту самозбереження все ж забезпечити видалення старих логів. Ну або просто відключити їх ведення.
  2. Ледачий. Для забезпечення ротації логів і економії місця на диску включити комбінацію "sv_log_onefile 0", "sv_logfilecompress 1" і "sv_logfilename_format %Y — %m — %d", додати в crontab
    find $HOME/log/server{1,2}/*.gz -type f -mtime +30 -delete
    , що дозволить обійтися без logrotate. Хороший, придатний варіант. У разі "нескінченних" карт можна сподіватися на якийсь час від часу трапляються оновлення серверів, при перезапуску гарантують ротацію логів, або примусово перезапускати карту хоча б раз в тиждень — додати в crontab запуск команди
    tmux -L socket1 send-keys "changelevel_next" Enter
    в години мінімального завантаження.
  3. Активний. Якщо є необхідність моніторити логи в реальному режимі часу, як їх аналізувати й обробляти, то можна використовувати можливості rsyslog демона. Плагін omfile — File Output Module ми використовували вище в обробці лода cron, а тут можна використовувати imfile — Text Input File Module.
Спробуємо налаштувати збереження чату гравців першого сервера в окремому протоколі. Створюємо (з-під root) файл /etc/rsyslog.d/srcds-20-chat.conf:
srcds-20-chat.conf
#/etc/rsyslog.d/srcds-20-chat.conf

module(load="imfile" mode="inotify")

# Моніторить всі *.log файли першого сервера
input(
type = "imfile"
tag = "srcds1:"
file = "/home/game/log/server1/*.log"
ruleset = "chat-1"
)

# $now - поточна дата, на момент запису лода, у форматі YYYY-MM-DD
template (name="chat1-log-name" type="string" string="/home/game/log/chat1-%$now%.log")

# Моніторимо загальний чат (say), командний (say_team), і steam id і ip гравців, що входять на сервер
ruleset(name = "chat-1") {
if ($msg contains [" say ", " say_team ", " connected, address "]) then {
action(
type = "omfile"
fileOwner = "game"
fileGroup = "game"
dynafile = "chat1-log-name"
)
}
}

При таких налаштуваннях, лог чату буде виглядати як:
Jul 23 10:40:46 server srcds1: L 07/23/2016 - 10:40:27: "Asuka<3><[U:1:12345678]><Blue>" say_team "Valar morghūlis"
Jul 23 10:40:46 server srcds1: L 07/23/2016 - 10:40:34: "Rei<4><[U:1:09876543]><Blue>" say "Valar dohaeris, desu"

Тут стандартний формат rsyslogd — дата+час, ім'я сервера (залізного), мітка з input, і сама рядок лода. Відмінність у секундах викликано буферизацією запису ігрових логів. При бажанні можна налаштувати додаткову перевірку тексту повідомлень на ключові слова з негайним повідомленням нас по електронній пошті (модуль ommail rsyslog)
Перевіряємо синтаксис, якщо все ок, то перезапускаємо демона.
# rsyslogd -N 2
# systemctl restart rsyslog

Якщо новий лог будете створювати в тому ж каталозі, звідки зчитуються вихідні (параметр file в секції input), переконайтеся, що його ім'я не потрапляє під маску файлів з секції input, які моніторить rsyslogd. А то вийде дуже, гм… рекурсивненько.
Повертаючись до налаштувань ведення логів, варто відзначити ще два параметри:
con_logfile ""

створює окремий файл журналу, куди записується все, що виводиться на консоль сервера. Ім'я файла вказується або з повним шляхом, або щодо каталогу ~/tf2/tf/ (не logs!). Якщо не вказувати розширення ".log", то воно додасться автоматично. Має аналогічний параметр командного рядка
consolelog <file>
— тільки там краще вже вказувати розширення, а то вийде забавно — при старті сервера створяться три консольних лода: спочатку запис піде в
~/tf2/bin/<file>
, потім
~/tf2/tf/<file>
, ну і нарешті в
~/tf2/tf/<file>.log
.
con_timestamp 0

при включенні (1), весь висновок консольний лог передуватимуть мітками часу, як в прикладі нижче. Якщо вказувати в командному рядку запуску разом з попереднім параметром
+con_timestamp 1 -consolelog <file>
, то мітки почнуться лише з третього файлу.
На відміну від серверних логів, запис у консольний лог йде порядково, і цілком коректно працює logrotate з параметром copytruncate.
Слід бути обережним з включенням запису цього, безумовно, корисного лода. Іноді на ігровий сервер щось знаходить, і він починає потужно спамити в консоль повідомленнями виду:
07/15/2016 - 14:59:59: DataTable warning: player: Out-of-range value (72483.898438/65536.000000) in SendPropFloat 'm_flLastDamageTime', clamping.
07/15/2016 - 14:59:59: DataTable warning: player: Out-of-range value (72492.539062/65536.000000) in SendPropFloat 'm_flLastDamageTime', clamping.
07/15/2016 - 14:59:59: DataTable warning: player: Out-of-range value (72479.742188/65536.000000) in SendPropFloat 'm_flLastDamageTime', clamping.

При швидкості потоку, як правило ~ 125 повідомлень в секунду, такими темпами файл з консольним логом приростає на ~ 64 Мб на годину, 1.5 Гб на добу, що особливо неприємно в разі "довгограючих" карт, так як при зміні карти ця помилка, як правило, зникає. Лікується або прописуванням критеріїв, що забезпечують регулярну ротацію карти, або смиренням з полуторагигабайтным логом на добу, тим більше, що стискаються вони непогано, а зберігати їх можна недовго.
Налаштовуємо ротацію цих логів, створивши з-під root файл /etc/logrotate.d/srcds-server:
srcds-server
#/etc/logrotate.d/srcds-server

/home/game/log/console*.log
{
su game game
daily
dateext
rotate 7
copytruncate
notifempty
missingok
compress
# compresscmd /home/game/logrotate-filter.sh
}

Перевіряємо логіку роботи:
# logrotate --debug --force /etc/logrotate.d/srcds-server

Можна туди додати милицю — рядок "compresscmd /home/game/logrotate-filter.sh", а сам ~/logrotate-filter.sh види:
logrotate-filter.sh
#!/bin/sh

/bin/grep -v ": DataTable warning:" | /bin/gzip -6 

тобто як архіватора буде викликатися не gzip а цей скрипт, який вхідний потік пропустить через grep, вирізаючи DataTable warning, а решта передаючи gzip, as planned.
до Речі, як варіант — можна включити дублювання лода в консоль (sv_logecho 1), вимкнути ведення основного лода (sv_logfile 0) і активувати запис консольного, і мати справу тільки з ним. В лог буде писатися мікс виду:
07/24/2016 - 18:50:46: DataTable warning: (class info_particle_system): Out-of-range value (-1.000000 / -1.000000)
07/24/2016 - 18:52:21: Attempted to add job to job queue that has already been completed
07/24/2016 - 18:57:11: DataTable warning: (class info_particle_system): Out-of-range value (-1.000000 / -1.000000)
07/24/2016 - 18:57:48: L 07/24/2016 - 18:57:48: "GLaDOS<20><BOT><Red>" triggered "player_builtobject"
07/24/2016 - 18:57:50: L 07/24/2016 - 18:57:50: "Companion Cube<34><BOT><Blue>" killed "GLaDOS<20><BOT><Red>" з "knife"
07/24/2016 - 19:00:24: L 07/24/2016 - 19:00:24: "AimBot<23><BOT><Red>" triggered "domination" проти "DeadHead<10><BOT><Blue>"
07/24/2016 - 19:00:25: L 07/24/2016 - 19:00:25: "AimBot<23><BOT><Red>" triggered "killedobject" (object "OBJ_SENTRYGUN")
07/24/2016 - 19:00:32: DataTable warning: info_particle_system: Out-of-range value (1.000000/1.000000)
07/24/2016 - 19:00:49: DataTable warning: (class info_particle_system): Out-of-range value (-1.000000 / -1.000000)

Єдина незручність — дублювання міток часу у вставок з ігрового лода. Можна вимкнути у консольного (con_timestamp 0), але це теж не діло. Якщо тільки пропускати цей лог через rsyslog, в ruleset парсити з допомогою regex і формувати новий файл з використанням свого шаблону. Але це для ентузіастів.
Логи сервера статистики
Сервер статистики HLstatsX у нас налаштований так, що логи його створюються в ~/stat/scripts/logs/, і по своєму вмісту практично аналогічні серверних логів, тому після початкової настройки, коли здасться, що все запрацювало, їх ми відключаємо, встановивши в ~/stat/scripts/hlstats.conf параметр "DebugLevel 0"
Прив'язка до Steam і QuickPlay
При запуску наших серверів напевно кидалися в очі повідомлення (рядки 2 і 7):
Setting breakpad minidump AppID = 232250
No account token specified; logging into anonymous game server account. (Use sv_setsteamaccount to login to a persistent account.)
ConVarRef room_type doesn't point to an existing ConVar
Executing dedicated server config file server1.cfg
...
Connection to game coordinator established.
tf_server_identity_account_id not set; not logging into account registered
*** ~/cfg/server1.cfg
...

Перше повідомлення повідомляє, що наш сервер підключений до майстер-серверів Valve "анонімно" (хоча хто знає, що сервер зливає при підключенні...), без входу в серверну обліковий запис. Друге повідомлення про те, що ми не зареєстровані в QuickPlay. Подивимося детальніше.
Серверна обліковий запис
Це відносно недавнє нововведення, анонсований в лютому 2014 року — hlds_announceабо у відкритому доступі, наприклад, тут. На даний момент актуально лише для двох ігор — Counter-Strike: Global Offensive і Team Fortress 2, причому для першої реєстрація обов'язкова. Реєстрація сервера дає як приємну, так і корисну особливості. Приємна — при зміні адреси або порти у нашого сервера, новий адресу автоматично оновиться в закладках у гравців, які свого часу додали. Ну і корисна — дозволяє тепер Valve, при виявленні що той чи інший ігровий сервер (поки тільки для CS:GO) порушує їх політику, не блокувати ip-адресу цілком, а лише конкретний Steam аккаунт порушника, на який куплена гра і до якого прив'язаний цей серверний профіль. А точніше — всі акаунти Steam, до яких прив'язаний номер телефону аккаунта-порушника. Велике полегшення для власників ігрових хостингів CS:GO, напевно.
Але повернемося до нашої гри. У згаданому анонсі Valve від 2014 року описаний процес реєстрації шляхом отримання ключа до api http://steamcommunity.com/dev, наступним запитом з ним до IGameServersService/CreateAccount і так далі. Для загального розвитку можна пройти через це всі, а можна (XXI століття все ж) перейти на сторінку http://steamcommunity.com/dev/managegameserversщо ми і зробимо. Там же наведено актуальні вимоги для реєстрації. На даний момент вони такі:
  • Ваш аккаунт Steam не повинен бути заблокований.
  • Ваш аккаунт Steam повинен мати необмежені права.
  • До вашого облікового запису Steam повинен бути прикріплений діючий номер телефону.
  • На вашому акаунті Steam повинна бути гра, для якої ви створюєте обліковий запис сервера.
  • Ви можете створити до 1000 записів серверів гри.
Краще не використовувати основний ігровий аккаунт, якщо він у вас є, а завести новий. Запускаємо клієнт Steam, реєструємо нову обліковий запис (п. 1 — ok), поповнюємо рахунок на еквівалент 5 USD (п. 2 — ok), у властивостях аккаунта прив'язуємо номер телефону (п.3 — ok), додаємо в бібліотеку ігор Team Fortress 2 (п. 4 — ок). Враховуючи позитивну відповідь на питання "Do VAC and Game bans apply to all accounts on a phone number?" у [Базі Знань] https://support.steampowered.com/kb_article.php?ref=8625-WRAH-9030)має сенс використовувати окремий телефонний номер, тільки для цього облікового запису. Достатньо лише прив'язати номер, активувати Steam Guard немає необхідності:
Game server login token
Якщо всі вимоги ми виконали, то переходимо на сторінку https://steamcommunity.com/dev/managegameservers, логинимся, якщо ще не, і в самому низу бачимо поля для отримання нового сертифіката. Заповнюємо. Виконуємо.
Create game server login token
Якщо все успішно, то в табличці ми бачимо наш gameserver login token:
New game server login token
ми прописуємо в ~/cfg/autoexec1.cfg:
autoexec1.cfg
//...

// Steam Gameserver Account
sv_setsteamaccount 3A820F219B470281C00IDDQD00A4D210

Запускаємо перший сервер, дивимося (рядки 2 і 8):
Setting breakpad minidump AppID = 232250
Logging into Steam game server account
ConVarRef room_type doesn't point to an existing ConVar
Executing dedicated server config file server1.cfg
...
Connection to Steam servers successful.
Public IP is 192.0.2.0.
Assigned persistent gameserver Steam ID [G:1:21].
VAC secure mode is activated.

Замість звичного "Assigned anonymous gameserver Steam ID [A:1:1724597452:5521]" ми бачимо тепер наш постійний Steam ID — [G:1:21]. "G" — GameServer, а раніше був "A" — AnonGameServer. Докладніше — у wiki.
Тепер на локальному комп'ютері запустимо Team Fortress 2 із звичайного, ігрового аккаунта, додаємо, якщо ще не наш сервер в закладки. Відкриваємо теку
C:\Program Files\Steam\userdata\<ігровий id>\7\remote\
. Там повинен бути файлик serverbrowser_hist.vdf, в якому зберігаються закладки та історія. Шукаємо в закладках наш сервер і бачимо, що тепер для нього прописаний серверний обліковий запис (рядок 9):
"Favorites"
{
"4"
{
"name" "192.0.2.0:27015"
"address" "192.0.2.0:27015"
"LastPlayed" "1476177442"
"appid" "0"
"accountid" "21"
}
}

Ідентифікатор accountid збігається з тим, який ми побачили в консолі сервера.
Необхідно мати на увазі, що отриманий нами токен при його невикористання протягом деякого часу блокується і необхідно використовувати команду "Regenerate token" на тій сторінці, де ми його отримували.
Так що якщо при запуску сервера видаються повідомлення виду:
Could not establish connection to Steam servers. (Result = 106)
enum_names.cpp (136) : Assertion Failed: Missing String for EResult (106)

то, як правило, це означає що токен недійсний — яких закінчився термін використання, або помилка в самій запису токена. Дивимося на сторінці http://steamcommunity.com/dev/managegameservers, чи не минув термін придатності токена. Знаючи свій Steam Web API Key можна використовувати інтерфейс IGameServersService — для кожного login_token дивитися його is_expired.
QuickPlay
UPDATE, поки номер готувався до друку: На даний момент the quickplay system is no longer in use for Team Fortress 2.
quickplay
Тому я просто залишу це здеь.
Для залучення гравців на сервер співтовариства була створена система QuickPlay. Вимоги до серверів час від часу змінюються, тому з актуальними критеріями краще ознайомитися на https://support.steampowered.com/kb_article.php?ref=2825-AFGJ-3513. На даний момент кілька основних вимог — сервер повинен бути зареєстрований, налаштування сервера, карти і модифікації повинні відповідати зазначеним у статті. Наш перший сервер виконує всі вимоги, за винятком реєстрації, якій зараз і займемося. Це не та реєстрація з використанням sv_setsteamaccount з секції вище, а окрема, для здійснення якої на свойм комп'ютері запускаємо клієнта Steam, логинимся з тієї ж обліковим записом, яку створили раніше — це не обов'язково, але так буде единообразнее. Запускаємо гру Team Fortress 2, відкриваємо в грі консоль —
~
, вводимо там команду cl_gameserver_create_identity. Нам у відповідь видасть:
cl_gameserver_create_identity
Request to create a game server account sent--please wait.
Game server account created successfully!
Set these convars on your game server to have it log in and receive benefits:
tf_server_identity_account_id 284181
tf_server_identity_token "18a>qPosnHYia?a"

Ось ці дві останні рядки ми прописуємо в ~/cfg/autoexec1.cfg:
autoexec1.cfg
//...

// QuickPlay
tf_server_identity_account_id 284181
tf_server_identity_token "18a>qPosnHYia?a"

Запускаємо перший сервер, дивимося (рядки 2, 9, 10):
Connection to game coordinator established.
Received auth challenge; signing into gameserver account...
*** ~/cfg/server1.cfg
...
Connection to Steam servers successful.
Public IP is 192.0.2.0.
Assigned persistent gameserver Steam ID [G:1:21].
VAC secure mode is activated.
Game server authentication: SUCCESS! Standing: Good. Trend: Steady
Successfully logged into gameserver account 284181.
For more information about gameserver accounts, visit https://support.steampowered.com/kb_article.php?ref=2825-AFGJ-3513.

Ну все, тепер чекаємо, коли до нас натовпом повалять гравці.
Якщо знадобиться тимчасово вивести сервер з QuickPlay, то не обов'язково правити autoexec1.cfg і перезавантажувати сервер. Можна використовувати команду tf_server_identity_disable_quickplay 1.
З часом, обіцяє Valve, ці tf_serveridentity облікові записи будуть замінені серверними обліковими записами.
Джерело: Хабрахабр
  • avatar
  • 0

0 коментарів

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