systemd + screen で Minecraft サーバを管理する

最近は暇な時間に tskserver という Minecraft サーバの環境をほじくり回しています. その一環で Minecraft サーバを systemd で管理するようにしました.

systemd で管理することのメリットとしては,systemd は頭がよいので,なんか良い感じに依存関係を考慮しながら起動順序を調整などをしてくれることがあげられます.

Minecraft のサーバは少し曲者で,Nginx や他のデーモンのようにシグナルを受け取ってくれるわけではないので,systemd の Unit file を書くときはサーバを安全に終了する (stop コマンドを走らせる) 方法を考えつつやる必要があります. この記事では,GNU screen を使って systemd から Minecraft サーバにコマンドを投げられるようにして安全な終了を実現します.

環境

OS は Ubuntu Server 16.04.4 LTS,Minecraft サーバの実装は Spigot です.たぶん公式サーバでも起動時の引数に nogui をつければいけるはず.

サーバのディレクトリはひとまず /home/k/tskserver に置いていてユーザ k で動かしています.

この記事でできること

  • Minecraft サーバを systemd で管理する
  • Minecraft サーバを 30 秒のカウントダウンとともに安全に終了できる
  • システム起動時に自動的に Minecraft サーバを起動できる
  • システム終了時でもネットワーク接続を維持しつつカウントダウンを待ち,Minecraft サーバを安全に終了できる

f:id:k5342:20180423023744p:plain

Minecraft サーバにコマンドを投げる

ここで GNU screen を使います. screen は detached なセッションに対して screen -S <session_name> -X stuff 'hogehoge' とコマンドを打つと session_name なセッションに対して hogehoge を標準入力 (?) として投げられるので便利です. 今回はこれを終了時に使います.具体的には終了時に save-allstop コマンドを投げるようにします.

systemd の Unit file を書く

おもむろに /etc/systemd/system/minecraft.service を作成し,以下を書きます.

[Unit]
Description=Minecraft Server
After=network-online.target

[Service]
User=k
Group=k
TimeoutStopSec=120
WorkingDirectory=/home/k/tskserver
ExecStart=/usr/bin/screen -Dm -S tskserver /usr/bin/java -Xms512M -Xmx5G -jar /home/k/tskserver/spigot.jar
ExecStop=/usr/bin/screen -S tskserver -X stuff "say tskserver will be shutdown in 30s\015"
ExecStop=/bin/sleep 10
ExecStop=/usr/bin/screen -S tskserver -X stuff "say tskserver will be shutdown in 20s\015"
ExecStop=/bin/sleep 10
ExecStop=/usr/bin/screen -S tskserver -X stuff "say tskserver will be shutdown in 10s\015"
ExecStop=/bin/sleep 5
ExecStop=/usr/bin/screen -S tskserver -X stuff "say tskserver will be shutdown in 5s\015"
ExecStop=/bin/sleep 5
ExecStop=/usr/bin/screen -S tskserver -X stuff "save-all\015"
ExecStop=/usr/bin/screen -S tskserver -X stuff "stop\015"
Restart=always

[Install]
WantedBy=multi-user.target

[Unit]

After=network-online.target

ネットワークがオンラインになってからこの Unit を起動するようにします. 同様にシステム終了時はこの Unit が終了してからネットワークが落ちるように順序を考慮してくれるようになります.

tskserver は fluentd を使ってログを収集しているのでこれに加えて After=fluentd.service をつけていて,Minecraft サーバが終了するまで fluentd も落ちないようになっています.

[Service]

TimeoutStopSec=

終了時のタイムアウト時間を秒単位で指定します. systemd は終了するぞってなったときに対象プロセスが終了するのを待ちますが,一定時間で SIGTERM が投げられて強制終了されてしまいます. デフォルトは 90 秒なので,これよりも長くカウントダウンを設定したかったり,プラグインを入れすぎて stop に時間がかかりすぎたりする場合は設定しておきましょう.

ExecStop=

終了時に実行するコマンドです.複数指定すると上から順に実行します. screen -S tskserver -X stuff "say hello\015" は,セッション名 tskserver のセッションに対して "say hello" と改行コード (0x0A, \015)を入力として送ります.改行コードなしだったり 8 進数以外だとコマンドが実行されないので注意.

Restart=always

サーバが勝手に終了した場合は常に自動で再起動するようにします.

バックアップなどをいい感じにしたい.あと冗長化構成組んでみたいけど需要あるんだろうか...?

tskserver はこれからも末永く運営していくつもりで,誰でも入れるサーバなので暇なひとは遊びに来てくれ~.[話を聞きに行く↗]