見出し画像

Linux ゲームサーバーをWEB&Discordで操作(汎用ゲームサーバー管理WEBサーバー)

自前のゲームサーバー立てたことありますか?
自前サーバーというのは、オンライン専用ではないゲームでマルチプレイする場合、接続するサーバーは自分で用意するシステムの事で、有名どころだとマインクラフト(Java版)は自前サーバーですね。
他には"Palworld"や"7 Days to Die"や"ARK"なんかでサーバーを建てた経験があります。
さてさて、こういったゲームで若干問題になるのが、サーバー立てた当人しか開始やシャットダウンできない起動時にシェルからコマンド打たないといけないなど、専用サーバーにしているならではの問題があります。まぁ専用ホストのセッションに合流形式だともっと可用性低いですが…。
というわけで参加者誰でも簡単に開始やシャットダウンなどの操作ができるシステムを作ってしまいましょう。


前提条件

環境

今回の記事で想定される環境は以下とします
Steamで配信されているゲームで、かつSteamCMDでサーバーを構築する際にLinux用のサーバーが用意されているゲームです。
別に環境が違えども、起動スクリプトがあり、それをシェルから実行するサーバーなら何でもOK!
OS:Linux (CentOS7/Ubuntu)
自前のPC/レンタルサーバー
各ゲームサーバーは用意済み

対象

Linuxを自力で管理できる人Orやる気のある人
Pythonの知識があるOrやる気のある人

システムの構成

システム概要

本システムを一言で説明すると、シェルから起動するタイプのサーバーをWEBサーバーの子プロセスとして実行して管理する。
WEBへのダイレクトアクセスと別途用意するDicord BOT連携操作の2種類の操作方法を設ける。

最小構成 : Flaskサーバーのみ
Discord BOT連携 : Flaskサーバー & DiscordBOT

  • メインシステム

    • Flask WEBサーバー
      各ゲームサーバーを"subprosess"ライブラリで子プロセスとして起動させる。
      サーバー管理者はこのWeb画面のボタンで操作可能。
      起動と停止にはそれぞれ専用のスクリプトを作成し、それを起動するようにすることで汎用性を持たせる。
      またアップデートにより任意のコマンドの実行と結果表示が可能になりました。専用の操作画面は存在しないので、直接URLを叩くか、Discordのボットから使用する前提です。

  • サブシステム

    • Discord BOT
      ゲーム参加者が簡単にサーバーの起動とシャットダウンができるように、DiscordのBOTに指示を出すと、BOTがFlask WEBサーバーのCGIにGETで指示を出して操作する。
      つまり、チャットで"/start palworld"みたいな感じで入力するだけでサーバーの起動や停止ができる

Discordを使う理由

第一に誰でも簡単に制御ができること。チャットで特定のメッセージを送るだけで簡単に操作できます。
また、WEBサーバーにアクセスさせてもいいが、平文通信なのとFlaskは公開向けのライブラリではないのでポート開放して使用するのは少々懸念があります。
しかし、DiscordのBOTなら同じコンピューター内で動作するので、localhostからFlaskに指示を出せばいいので安全です。
こういった理由からDiscordのBOTを使います。
勇者の方はWEBサーバーのポート開けてもいいです…。

使用方法と適用例

今回のシステムは、過去の経験上Linux版のサーバーを出しているゲームなら起動スクリプトから起動できること、終了の方法は別途通信プロトコルを設けていることが多いことが分かっていますので、複数タイトルで使用できるような仕組みで行きます。

後から追加されたタイトルごとの詳細説明は下記をご確認ください

Palworld(パルワールド)の場合

ARKの場合

Space Engineersの場合

詳細解説(7 Days to Dieで解説)

本記事は7dtdサーバーを再構築する時点で作成しているため、本作で解説となります。
このセクションは7dtdだけでなく、他のタイトルのサーバーを建てる際に必須な情報も含んでいるため適宜見てください。

このタイトルの場合は、サーバー構築時点で開始するためのスクリプトが作成されているのでそれを使いつつ、シャットダウンはTelnetを使います。
タイトルによってはここがRconだったりしますね。

ちなみにデフォルトでは無効になっているので、以下のようにTelnetを設定を有効にしておいてください。
ちなみにここで話をするのはA21バージョンです。
いつからか、ウェブの管理ターミナルが変わったのか、ただアクセスしただけではシャットダウンができなくなってしまったので、Tenletを使います。仕組みが分かっていれば、そのWEBのAPIに対してシャットダウンのコマンドを投げるような終了スクリプトを書いても大丈夫です。

	<!-- Admin interfaces -->
	<property name="WebDashboardEnabled"			value="true"/>				<!-- Enable/disable the web dashboard -->
	<property name="WebDashboardPort"				value="8081"/>				<!-- Port of the web dashboard -->
	<property name="WebDashboardUrl"				value=""/>					<!-- External URL to the web dashboard if not just using the public IP of the server, e.g. if the web dashboard is behind a reverse proxy. Needs to be the full URL, like "https://domainOfReverseProxy.tld:1234/". Can be left empty if directly using the public IP and dashboard port -->
	<property name="EnableMapRendering"				value="true"/>				<!-- Enable/disable rendering of the map to tile images while exploring it. This is used e.g. by the web dashboard to display a view of the map. -->

	<property name="TelnetEnabled"					value="true"/>				<!-- Enable/Disable the telnet -->
	<property name="TelnetPort"						value="8082"/>				<!-- Port of the telnet server -->
	<property name="TelnetPassword"					value=""/>					<!-- Password to gain entry to telnet interface. If no password is set the server will only listen on the local loopback interface -->
	<property name="TelnetFailedLoginLimit"			value="10"/>				<!-- After this many wrong passwords from a single remote client the client will be blocked from connecting to the Telnet interface -->
	<property name="TelnetFailedLoginsBlocktime"	value="10"/>				<!-- How long will the block persist (in seconds) -->

サーバーツールの構成

本ツールの構成は以下のようになっています。
メインのPythonスクリプト及びDiscordのbot用スクリプトで構成されています。
また、それぞれ別途Systemdのサービスに登録しておきます。(しなくてもいいですが)
これは何をしているかというと、Windowsで言うスタートアッププログラムの登録です。サーバーの電源を入れた時に、Webサービスとボットが立ち上がります。
Systemdに関しては本ツールを作るにあたり、以下でメモしたのでご確認ください。

Pythonの実行方法に関しては下記を参考にしてください

サーバー定義の作成

構成フォルダ内のserversのフォルダがサーバー構成を作成するフォルダになります。
この中に各ゲームごとのサーバー定義管理用のフォルダを作成します。
各記事で個別にこのツール内の定義方法を説明している場合、ここから先のセクションの話となります。

さらに、その中にはスタート、ストップ、アップデート、バックアップの4
つのスクリプトを入れます。
なお、最低スタートとストップがあればよいです。
オリジナルコマンドを作成する場合は"オリジナルコマンド作成方法"をご確認ください。
追記:アップデートで"stat.sh"と"port.txt"が追加されました。

start.sh

サーバーを開始するシェルスクリプトです。管理サーバーからこのスクリプトを引数なしで起動して、ゲームサーバーが立ち上がるように中身を記述します。

このスタートスクリプトのポイントはいくつかあります。
まず一つ目、20行目が実際のサーバーを起動するための行になります。
シェルスクリプトの中で既存のゲームサーバーを起動するためのスクリプトを呼び出しているという形になります。
次のポイントは二重起動を防ぐためのブロックです。
起動時にstat.txtという名前のテキストファイルを出力し、終了したらそのファイルを削除することで、二重起動をしないようにブロックするような機構を設けてあります。
そのため、実際にこれをコピペして使う場合は起動スクリプトの行だけを変更することになります。

stop.sh

サーバーを停止するためのスクリプトです。ゲームの仕様に応じて最適な方法で停止させるように記述します。

7 Days to Dieの場合は上記のようになります。
終了コマンドは"shutdown"で、それをtelnet経由で送信します。
Cent OSにはデフォルトでtelnetが入っていないので別途インストールしておいてください。
実際にサーバーを立てた後、一旦上記のスクリプトを実行してサーバーが停止することを確認してみることをお勧めします。

update.sh

こちらは手動で流しただけで、まだ未検証ですが中身だけ紹介します。
基本的にSteamCMDでのアップデートをそのまま書き込んだだけです。
ただし、アップデート中に起動されると困るので、ブロックファイルであるupdate.txtを出力するようにしています。

backup.sh

ボタン一つでセーブデータをバックアップするためのスクリプト
この例では、保存フォルダの中身をZIPに圧縮して専用のフォルダーに格納する手順となっています。名前はその日の日付で出来上がります。


ここからはアップデートで後から追加したスクリプトの話です。タイトルも7dtdではありません。

stat.sh (オプション)

space engineers対応で追加したスクリプトです。
サーバー実行中は"start.sh"が実行されっぱなしではなく、処理が戻ってきてしまうような場合に対応させたものです。
下記のように各タイトルごとにサーバーの起動状態を取得してステータスファイル"stat.txt"を出力するような処理を書いてください。
不要なタイトルではもちろん不要です。

port.txt

そのサーバーが使うポート番号を書いておくテキストです。
このファイルが存在する場合、サーバーリスト取得時にnetstatコマンドを使用してポートの監視を行います。
これにより、サーバーが本当に起動しているのかどうかのチェックができるようになります。
面倒ならこちらも不要です。

port.txtがある場合このようにポートが待ち受け状態に入るとステータスが変わります。※待ち受け開始=準備完了かどうかはサーバー設計者にしかわからないので目安くらいに考えてください。

操作方法及び機能

では、実際にサーバーの起動と終了をやってみましょう。
先ほどのサーバー定義を作成したら、プログラムを再起動してください。そうすることでサーバー定義が読み込まれます。

起動方法

  1. 最小構成

    • GameServer_WEB.pyを起動
      メインのFlaskWEBサーバーです。これは必須です

  2. Discord連携

    • GameServerbot.pyも起動
      連携のBotです。

Linuxでの起動方法は下記の通りです。
systemdへの登録をしたくない場合はnohupを使うことでシェルからログアウト後も実行できます。

動作確認だけの場合
$ python3 GameServer_WEB.py
$ python3 GameServerbot.py

systemdを使わずに立ち上げる場合
$ nohup python3 GameServer_WEB.py &
$ nohup python3 GameServerbot.py &

必要ライブラリ

下記コマンドを使用して必要ライブラリをインストールしてください。
なお、今後のアップデートなどにより、さらに追加が必要になることがあります。ライブラリ不足で起動できない場合はエラーメッセージを確認し、必要なライブラリを導入してください。

 #必須 
pip install requests
pip install flask
pip install cryptography
pip install flask_socketio
 #Discord  BOTも使う場合
pip install aiohttp
pip install discord

WEB操作パネルから操作

管理者であれば一番分かりやすいのがこのWebコントロールパネルです。
サーバー定義のフォルダ名がサーバー名となり、ステータス及び操作ボタンが表示された手抜ry…シンプルなものです。
というわけで、操作方法は簡単!!起動/停止ボタンを押すだけです。
もうお分かりかと思いますが、このボタンを押すことでstart.sh/stop.shが呼び出される仕組みです。
WEBへのアクセス方法はデフォルトの場合25564ポート(マイクラ-1)にしています。IPアドレス等はLinuxで建てる時点で大丈夫ですね。
他にアップデートとバックアップについても、各サーバーの横にあるボタンを押すことでスクリプトを呼び出すことができます。

起動ボタンを押すと、この関数が呼び出されます。

Discordからの操作

次はDiscordをチャットで操作する方法を見ていきましょう。
なお、すでにBOTアカウントを作成&サーバーに招待済みで、本ツールのGameServerbot.pyを立ち上げると、BOTが立ち上がるようになっている前提です。
トークンはスクリプト内に書くところがあります

BOTの作成方法は下記メモを確認してください

  • 全般
    本ツールのBOTは"サーバー管理"という名前のチャンネルに対して反応します。必ず作成してください。

  • コマンド方式
    /コマンド 引数

    • ヘルプ
      /help
      上記コマンドを入力することで、どんなコマンドが使えるのか、それはどういうものなのかの説明をしてもらえます。

  • 操作コマンド

    • list
      現在管理されているサーバーとそれらのステータス一覧を表示します。
      また、stat.shとport.txtが設定されている場合、それらが実行されステータスの更新がかかります。

    • start サーバー名
      ゲームサーバーを起動します

    • stop サーバー名
      ゲームサーバーを終了します

    • update サーバー名
      ゲームサーバーをアップデートします

    • backup サーバー名
      セーブフォルダをバックアップします

    • unique サーバー名
      後述のオリジナルコマンドのヘルプを表示します。

start時
stop
update
backup
  • システム操作コマンド

    • status
      サーバーのCPU使用率及びメモリ使用量を表示します。

    • shutdown
      サーバー本体をシャットダウンします。身内で「最後の人電源切っといて」という使い方をする前提のコマンドです
      ※ルート権限が必要なので、RootでSystemd起動している場合のみ機能します

ちなみにサーバーを実行中はこのようにステータスが変化する
  • exit
    Botを終了します。

オリジナルコマンド作成方法

本ツールは汎用性を重視していますが、各タイトルごとで任意のコマンドを追加し、実行したい場合は定義を自分で作成することが可能です。
詳しくは下記記事をご確認ください。

BOT限定機能

メモリ監視サーバー自動停止機能

本アップデート当時出たばかりのpalworldでメモリリークによるメモリ使用率の肥大化で落ちる問題に対処。それ以外でもゲーム専用でない場合に周囲を巻き込んで落ちる前にサーバーを止めるための機能です。
警告と停止の閾値を事前に設定し、空きメモリが減ると行動に移します。
これらのループは1分間隔で回っています。
警告は5分おきに行われ、警告時に停止の閾値に達していると停止を行います。

ここで言う強制終了とは、Botが勝手に"/stop"を実行するという意味です。

システムリソース表示機能

メモリ監視に伴い、せっかくなのでBOTのステータスの部分にCPU使用率とメモリ使用率を出すようにしました。
上記の1分ループ内で表示の更新が行われます。

ツールの配布について

以下よりツールを配布します。
詳細なコードが気になる方もぜひDLしてみてください。

https://script.google.com/macros/s/AKfycbysRqb7488rvLGPqOOhGlr0w513zIHC67BEPzJtPAKrAc4lKfDCmsB0mVL1Ha5BY5P0/exec?name=ゲームサーバー管理サーバー

アップデート情報

アップデートでの変更は記事にはサイレント反映されますので、具体的な変更内容はここで記載します。

  • Ver 1.0.0 2023/08/13 初版

  • Ver 1.1.0 2024/01/28 Palworld記念アップデート

    • BOTシステム

      • サーバーとチャンネルの取得方法を変更
        これにより、"サーバー管理"という名前のチャンネルを用意する必要があります。

      • コマンドの形式を変更

      • exitコマンド追加

  • Ver 1.2.0 2024/02/10 リソース監視アップデート

    • WEBシステム

      • CPU使用率及びメモリ使用状況を取得するためのCGI追加

    • BOTシステム

      • CPU使用率とメモリ使用率を取得できるように機能追加

      • 事前に設定したメモリ使用率に応じて警告や停止を行える機能追加

      • 現在のCPU使用率及びメモリ使用率をステータスに表示する機能追加

  • Ver 1.3.0 2024/02/12 オリジナルコマンド作成機能

    • WEBシステム

      • コントロールURLがオリジナルコマンドを受け付けるように変更

      • 各サーバーでオリジナルコマンド定義ファイルがある場合、読み込むように変更

    • BOTシステム

      • オリジナルコマンドを確認する"unique"コマンドを追加

      • オリジナルコマンドを実行しようとした際の動作を追加

  • Ver 1.4.0 2024/03/04 ステータスアップデート

    • WEBシステム

      • サーバーリスト取得時の動作変更

        • サーバー定義内にstat.shが存在する場合実行するように変更

        • port.txtにポート番号が書いてある場合、そのポートが待ち受けされているかどうかをステータスに反映するように変更

    • BOTシステム

      • port.txtが存在する場合でポートが待ち受けされている場合の表現を変更

まとめ

今回はゲームサーバー管理サーバーを作成しました。
過去にマイクラサーバー管理ツールなら作ったことがあるのですが、あれはマイクラに特化しすぎて他では使えないものになってしまいました…。
今回は起動や停止に任意のスクリプトを作成できる仕組みにしたことで、汎用性を持たせました。
また、操作方法にWEBサーバーと参加者向けのDiscordチャット機能を追加し、電源さえ入っていれば最初に始めたい人が点けることができるようになり、最後の人がシャットダウンまで行えるようになりました。
電源投入に関しては、電気代の都合上メインマシンの電源を入れてはおけませんが、BOT側にラズパイ等を使用してWOLパケットを投げられるようにするなんてのもいいかもしれませんね。そこまですれば管理者はサーバーを建てる作業さえすれば参加者が自由にプレイ可能ですね。

情報が役に立ったと思えば、僅かでも投げ銭していただけるとありがたいです。