きっかけ
- 強くなりたいしVPS借りて遊ぶぞ!
- せっかくVPS借りるしマイクラのサーバ立てたらみんな(1-4人)でマルチできるんじゃね?
- マイクラのサーバをサービスで動かしたらいちいちSSHせずに接続できるな、Realms借りなくてもいいじゃん!
- でもなんか勝手に使われるのもアレだし、第三者に入られても困るし、ログイン時ぐらいは通知を受け取れるようにしたい
- メールとかどうせ見ないしLineに通知するかー
##環境
- さくらのVPS 1GBプラン
- CentOS 7.6.1810
##要件・計画
-
ログイン・ログアウトの通知をラインに飛ばす
→「〇〇 joined/left the game」のログが拾えればいい
→grep
コマンドでgame
を含む行を抽出すればいける? -
ログイン・ログアウトの都度、その場で情報が欲しい
→マイクラサーバのログ出力を受け取る別プロセスを、マイクラサーバと一緒に動かしたい
→サービス実行時のシェルスクリプトでパイプをうまく繋げてやる? -
できるだけ簡単にしたい
→ シェルスクリプトで完結させたい+メモリ消費も異常に増大してないかは確認したい
##実装
###マイクラサーバ
以下の記事様を参考にし、マイクラのサーバがサービスとして動くようにします(感謝)
MinecraftServerをサービスとして起動する(Ubuntu14.04)
これにより今
-
run.sh
というシェルスクリプトがあり、サービス起動時にはこのスクリプトが実行される -
run.sh
を起動するマイクラサーバをminecraft_server
というサービス名で登録し、起動・終了・ステータスの確認ができる
という状態になっていると想定します。
###LINE通知
LINEのボットを作成済みで、curlによりボットに向けてメッセージを送ることができるようにします。
以下のようなサイトを参考にし、デベロッパ登録、チャンネル作成、ボット作成、トークン取得まで進めます。(感謝)
Google Apps ScriptでPushメッセージのLINE Botを作る。
かつ、受け取った文字列をそのままメッセージに投げてやるスクリプトも作成します。
以下のようなスクリプトを作成しました。注意点として:
- Access TokenとUser Idには自分のbotの値を入れてください
- sleep 1sは短時間に連続して送信しないための待ち処理です。待ち時間は適宜値を変えて使用してください
- 追記:文字列
$str
の出力を`${str:33}'としてやることで、ログの時刻などを削り内容のみが送られて来るようにできました
#!/bin/bash
while true
do
read v
if [ -z "$str" ]; then
break
fi
curl -v -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type:application/json' \
-H 'Authorization: Bearer {Access Token}' \
-d '{
"to": "{User Id}",
"messages":[
{
"type":"text",
"text":"'"${str:33}"'"
}
]
}'
sleep 1s
done
###スクリプト
あとはrun.sh
を以下のように書き換えてやれば、game
という文字列が含む行がラインに送信されます。
#!/bin/bash
cd /home/minecraft/minecraft
java -Xmx1024M -Xms1024M -jar minecraft_server.jar nogui | grep game --line-buffered | ./send.sh
できた。よかった
これをした後にsudo systemctl start minecraft_server
を実行すると以下のように無事ラインの方に通知が来ました。
そっかこの行も引っかかるのか・・・・まあいいか
実際にマイクラを立ち上げて自分でログイン・ログアウトして見ました
なんかいい感じにメッセージが来てますね、よかったよかった
##実装前実験
実は最初、以下のようにスクリプトを書いていたのですが何も送られて来ず、わりと長時間はまっていました。
#!/bin/bash
cd /home/minecraft/minecraft
java -Xmx1024M -Xms1024M -jar minecraft_server.jar nogui | grep game | ./send.sh
なんでだ??ということで色々調べるため、簡単なスクリプトを書いて実験しました。
####準備
まず、以下のようなスクリプトを作成しました。
#!/bin/bash
echo hoge
echo fuga hoge
sleep 1s
echo fuga hogehogehoge
echo pikopiko
echo piko fuga
sleep 1s
echo hogehoge
echo fugafuga
echo hogefuga
sleep 5s
####実行
一秒ごとに複数行適当な文字列が出力され、プログラムの終了前には5秒ほど待ちが入ります。
これを用意した上で、以下のコマンドを実行しました。
./test.sh | grep hoge
その結果、hogeを含む行だけが表示され、しかもechoでhogeを含む行が出力されるであろうタイミングで、grepの結果が表示されるという動作をしました。
次に、この後ろにラインへの送信スクリプトを繋げました。
./test.sh | grep hoge | ./send.sh
その結果、hogeを含む行だけが表示はされましたが、test.sh
が終了するタイミングで(つまりスクリプト末尾のsleep 5s
で待機した後に)ラインの送信が始まりました。
はえ〜・・・・
なんでかは調べてないのでわかりませんが、grepで後ろに別のスクリプトを繋げると、前のプログラムが終了するまでgrep結果を後ろに渡さないんですね
ということで検索したら、そのものズバリな記事がヒットしました(感謝)
grep の出力をバッファさせない
ので、--line-buffered
のオプションを入れたらうまくいきました。基本的なことなのかなあ
パフォーマンスが低下するかもとのことなので接続時メモリ状況などには注意する必要があるかもですね
##動作確認
念のため、ログ通知のスクリプトをサービスに含めた場合と含めない場合で消費メモリ量を比較して見ました。
grep
とsend.sh
も起動した場合
total used free shared buff/cache available
Mem: 991 858 73 0 59 23
Swap: 4095 192 3903
serverのみ起動した場合
total used free shared buff/cache available
Mem: 991 871 65 0 54 12
Swap: 4095 162 3933
大丈夫・・・だよなあ???
serverのみに比べて爆発的に増えたというわけでもなさそうですし、大丈夫じゃないかなあと