2022/01/10追記
このスクリプトは作りが甘いです。最低限の作りだし、少し前の記事なのでこちらの方が参考になるかもしれません。
こにゃにゃちわ=^_^=
昔々・・・
いや最近・・・
ウィルスにサーバーが破壊されたというのは記憶に新しい
そんでマイクラのワールドのサルベージにも成功し、サーバーは純正鯖からspigot鯖に変更したものの、被害があったってのは事実。
それは何かって、シェルスクリプト全損。
シェルスクリプト全部暗号化されてたのね。それもあってアドオンが使えるspigot鯖に移動したってのもあるんだが・・・
それでもしばらく使ってみて、アドオンじゃ補えない、シェルスクリプトだから出来る事ってのはある。
というわけで、作り直そう!!!!!!!
Spigot鯖を自動再起動させる
課題
ではまず課題。の前置き。
そもそも再起動させないと何が起きるのか。
今まで数日間連続で実際に稼働させてみると、メモリがたまりにたまりまくって、クラッシュしたりクソ重くなったりでまあ、身をもって再起動の大切さってのが分かりましたねハイ()
では本題
SimpleRestartというBukkit系鯖に使用できるアドオンが存在するのは既知の通り。
だが、なぜか動作しない
JavaScriptで書かれてるのか?そこらへん全くの無知なのだが、オンラインプレイヤーが存在しないと値を取得できずエラーで実行されない、てな感じっぽい。
あとこのアドオン、reloadコマンドを使うとカウントがリセットされてしまう。
再起動機能は、搭載しないとメモリが解放できずクラッシュしてしまう問題があるのでそれは避けなければならない。
じゃあどうするか
今まで、アドオンを使わずに対処してきた方法
-それはLinuxで実装されているシェルスクリプト。
今まで使ってきたじゃあないか!
という訳で、やっていきます。
サーバーのscreen稼働化
その前にサーバーをscreenで動作させます。プロセス名で取得するのも面倒臭いので、あらかじめscreenで名前を付けて仮想端末として実行させておくことで、コンソールにも干渉しやすくします。
・・・建前。
本音は多分プロセスに直接干渉できなくはないんだろうけど、今までscreen制御でやってきたので、今まで通りの方法をとります。
java -Xms12G -Xmx12G -jar spigot-1.16.4.jar nogui
今までこれを書いたシェルスクリプトを実行させるだけでそれ以外シェルスクリプトで干渉している部分は無かったのですが、干渉できるように実装します。
sudo apt install screen
でインストールします。
今まで書いていたシェルスクリプトの文をこっちに置き換える。
screen -AdmSU minecraft java -Xms12G -Xmx12G -jar spigot-1.16.4.jar nogui
オプション
-A 端末サイズがどうこう?みんなこれ使ってるっぽいから便乗()
-dm デタッチモードで起動する(サーバーコンソールが表示されない)
-S セッション名(スクリーン名)を付与する
-U UTF-8を理解する(意味があるのかは不明)
minecraftというスクリーンを作ってjavaコマンドを実行させるわけだね。
-Xms -Xmxは例によってメモリ割り当て容量の設定。
シェルスクリプトを書く
やっていこ~う
といっても、今回は定期的に実行することで再起動通知をして、stopコマンドを実行して、少し間を明けてスタートスクリプトを実行するっていう、それだけなんだけどね!!!
では記述
難しいことは何もありません。
#!/usr/bin/bashSCREEN_NAME="minecraft"
START="./start.sh"
screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "say サーバーをあと30秒後に再起動します。 \015"'
sleep 25
screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "say サーバー再起動まで残り5秒・・・ \015"'
sleep 1
screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "say サーバー再起動まで残り4秒・・・ \015"'
sleep 1
screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "say サーバー再起動まで残り3秒・・・ \015"'
sleep 1
screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "say サーバー再起動まで残り2秒・・・ \015"'
sleep 1
screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "say サーバー再起動まで残り1秒・・・ \015"'
sleep 1screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "kick @a サーバー再起動。一分ほどして接続し直してください。 \015"'
sleep 1
screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "stop \015"'
sleep 7
${START}
上二つのSCREEN_NAMEとSTARTは変数で、まあスクリーン名を変えてしまっても対応できるようにって感じ。まあ特に関係ないんすけど。
で
screen -p 0 -S ${SCREEN_NAME} -X eval 'stuff "say サーバーをあと30秒後に再起動します。 \015"'
これがチャット伝達部分
コンソールに「say サーバーをあと30秒後に再起動します。 \015」と入力してしまうわけ何ですね。
\015は特殊記号で、エンターキーを打鍵したことを意味します。C言語で言う「\n(改行)」って奴ですね。
sleepは秒数単位で待機命令を出すコマンド。
で最終的にマイクラで@a、全指定でkickコマンドを実行しstopコマンドを実行します。
kick挟むとメッセージが表示出来るからって、それだけの理由ですけど。
うおおお!!文ごっちゃぐちゃ書かれてもわかんねえええ!!!
という訳で実行結果↓
ではこれを定期的に実行(一時間毎)させて、自動で再起動しメモリを解放させるようにしませう。
crontabで設定する
crontab ってDebian系Linuxだとデフォルトで搭載されているのかな?おそらくインストール不要だと思いますが
sudo apt install cron で出来たはずなので念のため書いておく
そしたら
crontab -e
を実行
こんな感じで開く。基本は白紙・・・じゃないか、#コメントで英文が大量に書いてあった気がする。そちらはすべて削除しておけ~
で@reboot ファイルパス って記述されているのは分かると思いますが。
これは、パソコン起動時にスクリプトを実行するという項目。で、スタートスクリプトを実行しているわけですね。それだけ
こんな感じで追記。
分 時 日 月 曜日 シェルスクリプトファイルパス
という方式で記述。
アスタリスク記号は毎数を指します。
0 * * * *は毎週毎月毎日毎時0分の時実行する、実質一時間おきに実行するという意味なんですね。
この設定をすることで毎時0分になったとき、再起動スクリプトを自動で実行してくれるわけですね。わあ便利
いかがだったでしょうか。シェルスクリプトはアドオンとは別のメリットデメリットがあるので、使い分けると便利っぽいですね。
前に書いた記事もあるんですけど、
こんな感じでlatest.logファイルにチャットログが出力されるので活用出来る部分は最大限使って行きませう!
('ω')ノシ
この記事へのコメント
kokuma
途中までは実行されるのですが、突然止まり、 screen is terminating と表示されてしまいます。
kokuma
時間をおいたらなぜか起動できました
kokuma
エラーログもないのでどうすればいいか分からない状況です。
考えられる原因などを教えて下さい。
猫山さん。
> kokumaさん
>
> restart.shを手動で起動すると再起動できるのですが、cronで起動するとサーバーが閉じはするのですが、再び起動しません。
> エラーログもないのでどうすればいいか分からない状況です。
> 考えられる原因などを教えて下さい。
kokuma
https://imgur.com/gallery/f1WDFOp
こんな感じなんですけど、、、
猫山さん。
Discordか何かでやり取り出来ませんか?
> kokumaさん
>
> >猫山さん。
> https://imgur.com/gallery/f1WDFOp
> こんな感じなんですけど、、、
kokuma
Discord:Hexanitrohexaazaisowurtzitane #0759 です。
よろしくおねがいします。
ミネムラ
./reboot.shと手入力した場合はサーバーが正常に再起動するのですがcrontabから実行した場合は、アナウンスは正常に実行されサーバーも終了するものの、サーバーが起動しないという状態です。
原因としてどのようなことが考えられるでしょうか。
猫山さん。
>ミネムラさん
コメントありがとうございます。
crontabは性質上、crontabのディレクトリでスクリプトを実行します。
crontabに設定した時にフルパスでスクリプトを指定して実行しているのですが、crontabのディレクトリで実行されたreboot.shが「./activate.sh」を実行しても、カレントディレクトリ(crontabのディレクトリ、./指定)にactivate.shは存在しないため実行できていない物だと思います。私も悩んで同じ問題が起きました。
解決策としては、activate.shをフルパスで指定して実行する、activate.shが存在するディレクトリに移動(cd)してから実行すると大丈夫だと思います。
また、全く別の方法ですけど
https://nekoy3.net/2022/02/16/docker-spigot/
こういった方法もありますので、ある程度ゆとりが出来たらお試しください。
ミネムラ
返信いただきありがとうございます。
crontab内でのreboot.sh、activate.sh内のserver.jarの指定、reboot.sh内のactivate.shの指定すべてをフルパスで行ってみたのですが、crontabからではサーバーが起動できませんでした。。。
色々調べてみて、無理そうだったらご教授いただいた方法を試してみたいと思います!
猫山さん。
別プラットフォームでやりとり(Discord等)が出来るのであればスクショとか使ってやりとり出来ますよ
> ミネムラさん
>
> >猫山さん
> 返信いただきありがとうございます。
> crontab内でのreboot.sh、activate.sh内のserver.jarの指定、reboot.sh内のactivate.shの指定すべてをフルパスで行ってみたのですが、crontabからではサーバーが起動できませんでした。。。
> 色々調べてみて、無理そうだったらご教授いただいた方法を試してみたいと思います!
ミネムラ
しげる#9938です。