Какие данные можно получить с сервера CS и зачем это нужно
Администратор игрового сервера без мониторинга работает вслепую. Вы не знаете, упал ли сервер ночью, сколько игроков было на пике и какие карты собирают максимальный онлайн. Эти данные критичны для трёх задач: оперативное восстановление после сбоев, планирование обновлений и анализ активности аудитории.
Серверы Counter-Strike 1.6, CS:GO и CS2 отдают по сети стандартизированный набор метрик через протокол Source Query. Вы получаете статус онлайн или офлайн, количество игроков и максимум слотов, название текущей карты, версию сервера и список игроков с никами, счётом и временем на сервере. Для CS 1.6 используется движок GoldSource, для CS:GO - Source, для CS2 - Source 2. Протокол у всех трёх версий базируется на пакетах A2S_INFO и A2S_PLAYER, но в CS2 Valve добавила сжатие ответов и обязательный challenge перед запросом списка игроков. Без учёта этих нюансов ваш скрипт будет получать пустой ответ или ошибку.
Практическая польза от этих метрик прямая: триггер на статус сервера ловит падение за секунды, а не по жалобам игроков в Discord. График онлайна за неделю показывает, в какие дни комьюнити наиболее активно - под это вы подстраиваете ивенты и техобслуживание. Срез по картам выявляет, что de_dust2 держит 24 слота, а cs_office - 8, и вы меняете ротацию. Это не теория, а рабочий инструмент администратора, который обслуживает десятки серверов.
Если вы уже работаете с мониторингом других игровых проектов, принцип будет знаком. Для Minecraft-серверов мы разбирали аналогичную механику в гайде по мониторингу Minecraft, а для DayZ - в руководстве по настройке мониторинга DayZ. Подход с Source Query и Zabbix универсален.
Способы получения метрик: API, утилиты и сервисы
Есть три подхода к извлечению данных с игрового сервера. Первый - готовые онлайн-сервисы вроде GameTracker или BattleMetrics. Вы регистрируете сервер, получаете страницу со статистикой и базовый алертинг. Плюс в скорости запуска: пять минут, и мониторинг работает. Минус - жёсткие ограничения по кастомизации. Вы не можете добавить свою метрику, изменить интервал опроса или интегрировать данные в корпоративный дашборд. Сервисы подходят для одного-двух серверов, когда не нужна глубокая аналитика.
Второй подход - консольные утилиты GameDig или qstat. GameDig - Node.js-библиотека, которая умеет опрашивать более 200 игр, включая CS 1.6, CS:GO и CS2. Утилита парсит ответ сервера и выдаёт JSON, который легко разбирать в скриптах. qstat - более старая альтернатива на C, работает быстрее, но поддерживает меньше игр и сложнее в установке. Обе утилиты встраиваются в shell-скрипты и отдают данные в Zabbix через UserParameter.
Третий подход - прямые запросы к серверу через Source Query Protocol на Python или netcat. Вы сами формируете UDP-пакеты, отправляете на порт 27015 и парсите бинарный ответ. Максимальный контроль, никаких внешних зависимостей, но и максимум работы по обработке краевых случаев: сжатие в CS2, challenge-запросы, таймауты, блокировки при частых опросах.
Для продакшен-мониторинга я рекомендую GameDig. Утилита закрывает все различия между версиями CS, стабильно работает и легко интегрируется с Zabbix. Прямые запросы через сокеты оставьте для случаев, когда нужна уникальная метрика, которую GameDig не вытаскивает.
Использование GameDig для универсального опроса серверов
Установка GameDig выполняется одной командой при наличии Node.js и npm:
npm install -g gamedig
После установки утилита доступна глобально. Базовый синтаксис запроса:
gamedig --type <игра> <ip>:<port>
Для трёх версий Counter-Strike тип игры указывается по-разному:
- CS 1.6:
--type cs16 - CS:GO:
--type csgo - CS2:
--type cs2
Пример запроса к серверу CS:GO на 192.168.1.100:27015:
gamedig --type csgo 192.168.1.100:27015
Ответ возвращается в JSON. Разберём ключевые поля:
{
"name": "My CS:GO Server",
"map": "de_dust2",
"password": false,
"raw": { ... },
"maxplayers": 24,
"players": [
{ "name": "Player1", "score": 15, "time": 3600 },
{ "name": "Player2", "score": 8, "time": 1200 }
],
"bots": [],
"connect": "192.168.1.100:27015",
"ping": 12
}
Из этого вывода нас интересуют: name - название сервера, map - текущая карта, players.length - количество игроков онлайн, maxplayers - максимум слотов, ping - задержка ответа. Поле players - массив объектов с никами, счётом и временем в секундах.
Для парсинга JSON в shell-скрипте удобно использовать jq. Пример извлечения количества игроков:
gamedig --type csgo 192.168.1.100:27015 | jq '.players | length'
Пример получения названия карты:
gamedig --type csgo 192.168.1.100:27015 | jq -r '.map'
Флаг -r убирает кавычки из строкового значения - это важно для передачи данных в Zabbix, который ожидает чистую строку.
Прямые запросы к серверу через Source Query Protocol
Если вы по какой-то причине не можете использовать GameDig, работайте с протоколом напрямую. Source Query работает поверх UDP. Пакет A2S_INFO имеет заголовок из 5 байт: четыре байта 0xFF и один байт 0x54. Сервер отвечает бинарным пакетом, который нужно распарсить по спецификации Valve.
Пример на Python с использованием socket и struct:
import socket
import struct
def query_a2s_info(ip, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(3)
request = b'\xFF\xFF\xFF\xFF\x54Source Engine Query\x00'
sock.sendto(request, (ip, port))
response, _ = sock.recvfrom(4096)
sock.close()
# Пропускаем заголовок 0xFF 0xFF 0xFF 0xFF 0x49
data = response[5:]
# Парсим строки: название, карта, папка, игра
parts = data.split(b'\x00')
server_name = parts[0].decode('utf-8', errors='ignore')
map_name = parts[1].decode('utf-8', errors='ignore')
return server_name, map_name
print(query_a2s_info('192.168.1.100', 27015))
Код отправляет UDP-пакет с заголовком A2S_INFO и разбирает ответ, вытаскивая название сервера и карту. Для получения списка игроков используется пакет A2S_PLAYER с байтом 0x55, но в CS2 перед этим нужно отправить challenge-запрос: сервер возвращает число, которое вы подставляете в следующий пакет. GameDig делает это автоматически, в ручном режиме придётся реализовать двухэтапный обмен.
Предупреждение: частые запросы к серверу могут привести к временной блокировке вашего IP. Для CS2 Valve рекомендует интервал не менее 30 секунд. В Zabbix ставьте интервал опроса 60-120 секунд - это безопасно и достаточно для оперативного обнаружения проблем.
Интеграция с Zabbix: пошаговая настройка сбора метрик
Архитектура мониторинга проста: Zabbix-сервер или прокси обращается к Zabbix-агенту на хосте, агент выполняет внешний скрипт с GameDig, скрипт опрашивает игровой сервер по UDP и возвращает метрику. Игровой сервер и Zabbix-агент могут находиться на одной машине или на разных - во втором случае скрипт просто обращается к удалённому IP.
Если вы строите мониторинг для целого кластера игровых серверов, посмотрите подходы к балансировке нагрузки из нашего руководства по балансировке для кластера CS2. Мониторинг и балансировка работают в связке: метрики онлайна определяют, куда направлять новых игроков.
Написание скрипта сбора данных для Zabbix
Создайте файл /etc/zabbix/scripts/cs_query.sh. Скрипт принимает три аргумента: IP-адрес, порт и тип метрики. Тип метрики - одно из значений: status, players, map, maxplayers, name.
#!/bin/bash
IP=$1
PORT=$2
METRIC=$3
GAME_TYPE="csgo" # замените на cs16 или cs2 при необходимости
# Путь к gamedig
GAMEDIG="/usr/bin/gamedig"
# Таймаут запроса - 5 секунд
TIMEOUT=5
# Выполняем запрос с таймаутом
RESULT=$(timeout $TIMEOUT $GAMEDIG --type $GAME_TYPE $IP:$PORT 2>/dev/null)
# Если запрос не вернул данных - сервер недоступен
if [ -z "$RESULT" ]; then
if [ "$METRIC" == "status" ]; then
echo 0
else
echo "N/A"
fi
exit 0
fi
# Извлекаем нужную метрику через jq
case $METRIC in
status)
echo 1
;;
players)
echo "$RESULT" | jq '.players | length'
;;
map)
echo "$RESULT" | jq -r '.map'
;;
maxplayers)
echo "$RESULT" | jq '.maxplayers'
;;
name)
echo "$RESULT" | jq -r '.name'
;;
*)
echo "Unknown metric"
exit 1
;;
esac
Сделайте скрипт исполняемым:
chmod +x /etc/zabbix/scripts/cs_query.sh
Проверьте работу вручную:
/etc/zabbix/scripts/cs_query.sh 192.168.1.100 27015 status
/etc/zabbix/scripts/cs_query.sh 192.168.1.100 27015 players
/etc/zabbix/scripts/cs_query.sh 192.168.1.100 27015 map
Скрипт возвращает 1 для статуса онлайн, число игроков и название карты. При недоступности сервера status возвращает 0, остальные метрики - строку N/A. Эта логика нужна для корректной работы триггеров Zabbix.
Теперь привяжите скрипт к Zabbix-агенту. В файле /etc/zabbix/zabbix_agentd.conf добавьте строку:
UserParameter=cs.server[*],/etc/zabbix/scripts/cs_query.sh $1 $2 $3
Перезапустите агент:
systemctl restart zabbix-agent
Проверьте, что Zabbix-сервер видит новый ключ. С Zabbix-сервера выполните:
zabbix_get -s <ip_агента> -k cs.server[192.168.1.100,27015,status]
Если получаете 1 - скрипт работает.
Создание шаблона Zabbix для игрового сервера CS
Шаблон - переиспользуемая сущность. Один раз настроив элементы данных и триггеры, вы привязываете шаблон к десяткам узлов сети, меняя только макросы. Создайте шаблон с именем Template CS Server.
Элементы данных для шаблона:
| Имя | Ключ | Тип | Интервал |
|---|---|---|---|
| CS Server Status | cs.server[{$SERVER_IP},{$SERVER_PORT},status] | Zabbix агент | 60s |
| CS Server Players | cs.server[{$SERVER_IP},{$SERVER_PORT},players] | Zabbix агент | 60s |
| CS Server Map | cs.server[{$SERVER_IP},{$SERVER_PORT},map] | Zabbix агент | 120s |
| CS Server Max Players | cs.server[{$SERVER_IP},{$SERVER_PORT},maxplayers] | Zabbix агент | 300s |
| CS Server Name | cs.server[{$SERVER_IP},{$SERVER_PORT},name] | Zabbix агент | 300s |
Макросы шаблона:
{$SERVER_IP}- IP-адрес игрового сервера{$SERVER_PORT}- порт сервера (по умолчанию 27015){$GAME_TYPE}- тип игры: cs16, csgo или cs2{$PLAYERS_WARN}- порог низкого онлайна для предупреждения (по умолчанию 5)
Триггеры:
- Server is down - высокая важность. Условие:
cs.server[{$SERVER_IP},{$SERVER_PORT},status].last()=0. Срабатывает при недоступности сервера. - Low online - средняя важность. Условие:
cs.server[{$SERVER_IP},{$SERVER_PORT},players].last()<{$PLAYERS_WARN}. Предупреждает о падении онлайна ниже порога. - Map changed - информационная важность. Условие:
cs.server[{$SERVER_IP},{$SERVER_PORT},map].diff()=1. Фиксирует смену карты для истории.
Привяжите шаблон к узлу сети, укажите макросы под ваш сервер - мониторинг заработает. Для серверов за пределами вашей сети, где нет возможности установить Zabbix-агент, используйте внешний мониторинг через трекер. Этот подход позволяет опрашивать серверы любого хостинга.
Настройка оповещений: как не пропустить падение сервера
Метрики без алертов - это архив. Администратор узнает о падении сервера, когда откроет дашборд, а не когда сервер упал. Настройте действие в Zabbix, которое реагирует на триггер «Server is down».
Создайте действие с условием: триггер имеет важность «Высокая» и имя содержит «Server is down». Операция - отправка сообщения через webhook в Telegram. Zabbix поддерживает нативный webhook Telegram с версии 5.0. Настройка: создайте бота через @BotFather, получите токен, узнайте chat_id вашего аккаунта или группы. В Zabbix перейдите в «Администрирование» → «Типы оповещений» → «Telegram», вставьте токен. В действии выберите тип оповещения Telegram и укажите chat_id.
Сообщение настройте с макросами:
🚨 Сервер {HOST.NAME} недоступен!
Дата: {EVENT.DATE} {EVENT.TIME}
Метрика: статус = 0
IP: {$SERVER_IP}:{$SERVER_PORT}
Эскалация - второй уровень оповещений. Если сервер не восстановился за 10 минут, Zabbix отправляет сообщение старшему администратору. В том же действии добавьте шаг эскалации с задержкой 600 секунд и другим получателем. Это страхует от ситуации, когда дежурный администратор пропустил уведомление.
Настройте время восстановления триггера - 60 секунд. За это время сервер должен стабильно отвечать на запросы, прежде чем триггер закроется. Без задержки восстановления вы получите флуд уведомлений при кратковременных сбоях сети.
Визуализация: строим дашборд для мониторинга серверов CS
Дашборд превращает поток метрик в картинку, которую вы считываете за секунды. В Zabbix создайте дашборд «CS Servers Overview» с тремя виджетами.
Первый виджет - «Состояние триггеров». Показывает все проблемные серверы с цветовой индикацией: красный - высокая важность, жёлтый - средняя. Настройте фильтр по группе узлов, куда входят игровые серверы. Этот виджет - первое, что вы видите при открытии дашборда, и он сразу отвечает на вопрос «есть ли проблемы».
Второй виджет - «График» онлайна за последние 24 часа. Источник данных - элемент «CS Server Players». График показывает суточные колебания: когда приходит ядро аудитории, в какие часы сервер пустует. Эти данные нужны для планирования рестартов и обновлений - вы ставите техработы на мёртвое время, а не на пик онлайна.
Третий виджет - «Таблица» со списком серверов. Столбцы: имя узла, текущий онлайн, максимум слотов, текущая карта, статус. Таблица даёт быстрый обзор всей инфраструктуры без проваливания в каждый сервер.
Для более продвинутой визуализации экспортируйте данные в Grafana через плагин Zabbix. В Grafana настройте источник данных Zabbix, создайте дашборд с графиком онлайна по всем серверам и heatmap по картам. Heatmap покажет, какие карты держат максимальный онлайн в разрезе часов и дней. Это сильный инструмент для анализа популярности контента, но требует дополнительной настройки плагина и времени на построение панелей.
Особенности мониторинга разных версий: CS 1.6, CS:GO и CS2
Три версии Counter-Strike используют разные движки, и это влияет на доступность метрик. CS 1.6 на движке GoldSource поддерживает A2S_INFO и отдаёт базовую информацию: название сервера, карту, количество игроков и максимум слотов. A2S_PLAYER может не работать без установленного плагина на стороне сервера - например, AMX Mod X с модулем запросов. Если вы администрируете старые серверы 1.6, проверьте, что плагин активен, иначе список игроков будет пустым.
CS:GO на движке Source имеет полную поддержку Source Query. A2S_INFO и A2S_PLAYER работают из коробки, без дополнительных настроек. Вы получаете детальный список игроков с никами, счётом и временем. Никаких подводных камней нет - это самая простая версия для мониторинга.
CS2 на Source 2 вносит два усложнения. Первое - сжатие ответов. Сервер может вернуть сжатый пакет, если вы установили соответствующий флаг в запросе. GameDig обрабатывает это автоматически, но при ручной реализации через сокеты нужно распаковывать данные. Второе - challenge перед A2S_PLAYER. Вы отправляете пакет 0x55, сервер возвращает challenge-число, вы повторяете запрос с этим числом. Без challenge сервер просто игнорирует запрос. GameDig скрывает оба нюанса, поэтому для CS2 я настоятельно рекомендую использовать именно утилиту, а не писать велосипед на сокетах.
Общая рекомендация для всех версий: всегда указывайте правильный тип игры в GameDig (cs16, csgo, cs2). Тип определяет, какой протокол и какой парсер ответа будет использован. Ошибка в типе даст невалидный JSON или пустой ответ.
Обеспечение безопасности при мониторинге
Мониторинг не должен открывать вектор атаки на игровую инфраструктуру. Порт Source Query - обычно 27015 - принимает UDP-пакеты от любого источника. Если злоумышленник узнает IP вашего сервера, он может заспамить порт запросами и вызвать деградацию производительности или временную блокировку легитимного мониторинга.
Ограничьте доступ к порту запросов на уровне брандмауэра. Разрешите входящие UDP-пакеты на порт 27015 только с IP-адреса вашего Zabbix-сервера или прокси. Пример правила iptables:
iptables -A INPUT -p udp --dport 27015 -s <IP_Zabbix> -j ACCEPT
iptables -A INPUT -p udp --dport 27015 -j DROP
Если Zabbix-сервер и игровой хост находятся в разных дата-центрах, поднимите VPN-туннель между ними и закройте порт 27015 от внешнего мира полностью. Мониторинг будет ходить внутри зашифрованного туннеля.
Не храните RCon-пароли в скриптах мониторинга. RCon - протокол удалённого управления сервером, и его пароль даёт полный контроль над игровым процессом. Скрипт сбора метрик не использует RCon, ему достаточно Source Query. Если вы расширите скрипт для отправки команд на сервер, выносите пароль в отдельный файл с правами 600 и читайте его через source или cat.
При использовании внешних сервисов вроде GameTracker убедитесь, что они не раскрывают конфиденциальную информацию. Публичная страница сервера должна показывать только название, онлайн и карту - не IP, не RCon-порт, не внутренние комментарии администратора.