α版としてリリースされたpalworldのdedicatedサーバーは定期的な再起動が必要です。
メモリの消費量が激しく、環境によっては日に複数回のプロセスの再起動が必要になります。
systemdのtimer
やRuntimeMaxSec
を使う方法もありますが、今回はcron
を使って制御をしてみました。
cronで扱うためにサービスをユーザーレベルに変更した、というのが今回の経緯です。
おそらくもっとシンプルなやり方もあるのでしょうが、自分の忘備録として残しておきます。
環境
名前 | バージョン |
---|---|
OS | Ubuntu 22.04 |
基本的な構築は下記の記事を踏襲しています。
起動シェルとサービスの登録(とcron)が変更箇所になります。
起動用のシェルの作成
知識
tmux
はscreen
と同じような仮想ターミナルを作成することができます。
下記の記事が参考になります。
https://qiita.com/shin-ch13/items/9d207a70ccc8467f7bab
今回はサーバーの起動をtmux
経由で起動します。
起動時のログが消えず、万が一エラーが発生していた際に後から追うことができます。
起動シェル
/home/palworld/Steam/steamapps/common/PalServer/boot.sh
起動シェル例
#!/bin/bash
TMUX_NAME=palworld-server
case $1 in
start)
tmux new-session -s $TMUX_NAME -d "/home/palworld/Steam/steamapps/common/PalServer/PalServer.sh -useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS"
sleep 10;;
stop)
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Broadcast The-server-will-restart-in-60-seconds.Please-prepare-to-exit-the-game."
sleep 30
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Broadcast The-server-will-restart-in-30-seconds.Please-prepare-to-exit-the-game."
sleep 20
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Broadcast The-server-will-restart-in-10-seconds.Please-prepare-to-exit-the-game."
sleep 5
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Broadcast The-server-will-restart-in-5-seconds.Please-prepare-to-exit-the-game."
sleep 1
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Broadcast The-server-will-restart-in-4-seconds.Please-prepare-to-exit-the-game."
sleep 1
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Broadcast The-server-will-restart-in-3-seconds.Please-prepare-to-exit-the-game."
sleep 1
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Broadcast The-server-will-restart-in-2-seconds.Please-prepare-to-exit-the-game."
sleep 1
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Broadcast The-server-will-restart-in-1-seconds.Please-prepare-to-exit-the-game."
sleep 5
/home/palworld/rcon/rcon -a "127.0.0.1:25575" -p password "Shutdown 5 shutdown "
sleep 5;;
*)
echo "start | stop"
esac
サービスの登録
ユーザー固有の.service
ファイルの作成
知識
ユーザー固有のサービスにするためには、以下の2つが必要になります。
- 該当のユーザーにsshでログインができること
-
~/.config/systemd/user/"service-name".service
のユニットファイル
ユニットファイル
今回は以下のファイルを作成しました。
必要に応じて所有者を変更しておいてください。
~/.config/systemd/user/palworld-dedicated.service
ユニットファイル例
[Unit]
Description=Palworld Dedicated Server
[Service]
WorkingDirectory=/home/palworld/Steam/steamapps/common/PalServer/
ExecStart=/bin/bash /home/palworld/Steam/steamapps/common/PalServer/boot.sh start
ExecStop=/bin/bash /home/palworld/Steam/steamapps/common/PalServer/boot.sh stop
TimeoutStartSec=300
Restart=always
RemainAfterExit=yes
[Install]
WantedBy=default.target
ユーザーレベルのユニットファイルでは、通常のユニットファイルとは使えるディレクティブが違います。
基本的には同じものが使えますが、User
やGroup
が使えません。
もし、すでにサービスとして/etc/systemd/system/hogehoge.service
を登録しているのであれば、解除をしておいてください。
サービスの起動
知識
対象のユーザーにsshでログインしてから実行してください。
ユーザー固有のサービスの起動にはsudo
をつける必要がありません。
その代わりに--user
をつけて実行する必要があります。
su - hogehoge
では失敗するため注意が必要です。
おそらく下記のエラーで弾かれます。
Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined (consider using --machine=<user>@.host --user to connect to bus of other user)
起動
サービスファイルを再読み込みします。
systemctl --user daemon-reload
サービスを起動します
systemctl --user start palworld-dedicated.service
一度状態を確認します。
systemctl --user status palworld-dedicated.service
結果
palworld@palworld:~$ systemctl --user status palworld-dedicated.service
● palworld-dedicated.service - Palworld Dedicated Server
Loaded: loaded (/home/palworld/.config/systemd/user/palworld-dedicated.service; enabled; vendor preset: enabled)
Active: active (exited) since Mon 2024-02-05 11:01:16 JST; 4h 50min ago
Process: 10005 ExecStart=/bin/bash /home/palworld/Steam/steamapps/common/PalServer/boot.sh start (code=exited, status=0/SU>
Main PID: 10005 (code=exited, status=0/SUCCESS)
Tasks: 40 (limit: 38376)
Memory: 6.1G
CPU: 4h 6min 35.718s
CGroup: /user.slice/user-1001.slice/user@1001.service/app.slice/palworld-dedicated.service
├─10008 tmux new-session -s palworld-server -d "/home/palworld/Steam/steamapps/common/PalServer/PalServer.sh -use>
├─10009 /bin/sh /home/palworld/Steam/steamapps/common/PalServer/PalServer.sh -useperfthreads -NoAsyncLoadingThrea>
└─10018 /home/palworld/Steam/steamapps/common/PalServer/Pal/Binaries/Linux/PalServer-Linux-Test Pal -useperfthrea>Feb 05 11:01:16 palworld systemd[786]: Started Palworld Dedicated Server.
また、tmux
のセッションを確認してみます。
tmux ls
結果
palworld@palworld:~$ tmux ls
palworld-server: 1 windows (created Mon Feb 5 11:01:16 2024)
tmuxのセッションにアタッチする際は以下
デタッチはctlr+b
→ d
tmux a palworld-server
結果
Shutdown handler: initalize.
Increasing per-process limit of core file size to infinity.
dlopen failed trying to load:
steamclient.so
with error:
steamclient.so: cannot open shared object file: No such file or directory
[S_API] SteamAPI_Init(): Loaded '/home/palworld/.steam/sdk64/steamclient.so' OK. (First tried local 'steamclient.so')
CAppInfoCacheReadFromDiskThread took 2 milliseconds to initialize
dlmopen steamservice.so failed: steamservice.so: cannot open shared object file: No such file or directory
Setting breakpad minidump AppID = 2394010
[S_API FAIL] Tried to access Steam interface SteamUser021 before SteamAPI_Init succeeded.
[S_API FAIL] Tried to access Steam interface SteamFriends017 before SteamAPI_Init succeeded.
[S_API FAIL] Tried to access Steam interface STEAMAPPS_INTERFACE_VERSION008 before SteamAPI_Init succeeded.
[S_API FAIL] Tried to access Steam interface SteamNetworkingUtils004 before SteamAPI_Init succeeded.
問題がなければ一度サービスを停止します。
systemctl --user stop palworld-dedicated.service
cronの登録
再起動したい時間に合わせてcron
を記載してください。
下記は11時、23時に再起動するcron
です。
0 11 * * * XDG_RUNTIME_DIR=/run/user/$(id -u) systemctl --user restart palworld-dedicated.service
0 23 * * * XDG_RUNTIME_DIR=/run/user/$(id -u) systemctl --user restart palworld-dedicated.service
XDG_RUNTIME_DIR=/run/user/$(id -u)
を記載しないとエラーを吐いて、再起動をスキップします。
syslogからログを確認するか、systemctl --user status
からアップタイムを確認することで再起動されたかを確認することが出来ます。
戯言
cronではsudoを使えない、というところか模索が始まりました。
セキュリティリスクを減らす観点からrootログインを無効化したかったため、サービスをユーザーレベルに落とし込むことで解決しました。
検証はしていませんが、tmuxを経由せず、サーバー起動のシェルを直接叩いて、サービスをワンショットにすることでoncalenderによる再起動をする、というのがシンプルな解決方法な気がします。
cronにXDG_RUNTIME_DIR=/run/user/$(id -u)
を記載する必要がある、という情報もいろんな先駆者が記事を残してくれていたおかげですぐにたどり着くことができました。
ありがたい限りです。