見出し画像

Minecraftサーバーを構築しよう!!!!!【総集編】

前書き

マイクラサーバー記事の総集編となります!
前回までの記事はこちらからどうぞ!!

第一弾『Raspberry PiでMinecraftサーバーを構築しよう!』
第二弾『DiscordBotでMinecraftサーバーを動かそう!!』
第三弾『統合版でJava版Minecraftサーバーにログインしよう!!!』
第四弾『GoogleDriveでMinecraftサーバーを管理しよう!!!!』

今回の記事はこれまでのマイクラサーバーの記事を踏まえて、修正や改変を行ったものにな(るつも)(でい)ます😊
とりあえずこれまでに作成したプログラムは改善の有無に関わらず全部あげますが、それだけだと動かないと思うので以前の記事もみてね!!ステマ

あとひとつ謝っておくと、前回の記事内容の沿っても実はドライブに保存されないです。まあこんな記事見てる時点で色々な記事見てるだろうし、大丈夫っしょ!!
その辺りも記載するので許してください!何でもしますから!!
ということで今回もやってまいります!!

用意するもの

・RaspberryPi
・PC
・やる気、勇気、努力、勝利を掴み取れ!!!(友情はいりません)

あんなこと。こんなこと。あったでしょう。

フォルダ全体

まずはね、これまでに作成したファイルの構成を見ていきましょう。

mcserver/
 ┣ backup.sh
 ┣ banned-ips.json
 ┣ banned-players.json
 ┣ bukkit.yml
 ┣ cache/
 ┣ command.txt
 ┣ commands.yml
 ┣ config/
 ┣ distart.sh
 ┣ distop.sh
 ┣ eula.txt
 ┣ help.yml
 ┣ libraries/
 ┣ logs/
 ┣ msdis.py
 ┣ msdis.py.bak
 ┣ ops.json
 ┣ permissions.yml
 ┣ plugins/
 ┣ restore.sh
 ┣ save.sh
 ┣ server.jar
 ┣ server.propaties
 ┣ spigot.yml
 ┣ start.sh
 ┣ stop.sh
 ┣ update.sh
 ┣ usercache.json
 ┣ version.txt
 ┣ version_history.json
 ┣ versions/
 ┣ whitelist.json
 ┣ world/
 ┣ world_nether/
 ┗ world_the_end/

これまで

こんな感じでした。
きったないですね〜〜!!
フォルダがなんのために存在してるのか知らなさそうな配置になってます。
なんならドライブのマウント用フォルダはmcserverフォルダ外です。わかりずれ〜〜

なので、きれいにまとめたものがこちらになります!
太字が新規ファイル/フォルダ名、右矢印(→)が変更したファイル/フォルダ名、スラッシュ(/)がフォルダ名となってます。

mcserver/ → minecraft_server/
 ┣ minecraft_data/
 
┃ ┣ banned-ips.json
 ┃ ┣ banned-players.json
 ┃ ┣ bukkit.yml
 ┃ ┣ cache/
 ┃ ┣ commands.yml
 ┃ ┣ config/
 ┃ ┣ eula.txt
 ┃ ┣ help.yml
 ┃ ┣ libraries/
 ┃ ┣ logs/
 ┃ ┣ ops.json
 ┃ ┣ permissions.yml
 ┃ ┣ plugins/
 ┃ ┣ server.jar
 ┃ ┣ server.propaties
 ┃ ┣ spigot.yml
 ┃ ┣ usercache.json
 ┃ ┣ version.txt → server_version.txt
 ┃ ┣ version_history.json
 ┃ ┣ versions/
 ┃ ┣ whitelist.json
 ┃ ┣ world/
 ┃ ┣ world_nether/
 ┃ ┗ world_the_end/
 ┣ server_function/
 ┃ ┣ start.sh → server_start.sh
 ┃ ┣ stop.sh → server_stop.sh
 ┃ ┣ save.sh → server_save.sh
 ┃ ┣ update.sh → server_update.sh
 ┃ ┣ /etc/systemd/system/ms.service →minecraft_server.service
 
┃ ┣ /etc/systemd/system/ms-save.service
 ┃ ┃                      → minecraft_server_save.service
 ┃ ┗ /etc/systemd/system/jar.service → minecraft_server_update.service
 ┣ discord_bot/
 ┃ ┣ distart.sh → bot_start.sh
 ┃ ┣ distop.sh → bot_stop.sh
 ┃ ┣ msdis.py → bot_minecraft.py
 ┃ ┣ msdis.py.bak →  
 ┃ ┣ command.txt → bot_command.txt
 ┃ ┗ /etc/systemd/system/dis.sevice → minecraft_server_bot.service
 ┗ google_drive/
      ┣ drive_start.sh
      ┣ drive_stop.sh
      ┣ backup.sh → drive_backup.sh
      ┣ restore.sh → drive_restore.sh
      ┣ minecraft_server_drive.service
      
┗ ~/google_drive → drive_mount/

これから

それなりにきれいになりました。
ファイル/フォルダ名は長くなりましたが、何に使用されているのかよりわかりやすくなりましたね。プログラムしっかりやるなら命名規則とかも勉強しなきゃなー、と無限に思ってます。
これをベースに進めて行くので、何度も振り返りに来てください。

大別フォルダ

大別したフォルダを見ていきますか。

minecarft_server/
ここに全てが入るようにしました。
大本のファイルになります。
アドレスは~/minecraft_serverもしくは/home/ubuntu/minecraft_serverとなります。(私の場合、ユーザーネームがubuntu。)

minecraft_data/
名前通りマイクラのデータが入っています。
サーバーを立てた際に生成されるデータが入っており、基本触らないようになってます。
ドライブに複製する際に、バージョン情報も一緒に保存したかったため、server_version.txtだけ追加しています。(直でこのファイルを編集とかはないので、セーフ(?)

server_function/
サーバー関連の機能(起動や停止等)を管理したフォルダになります。
厳密に決めてるわけではないですが、minecraft_data/へ作用するファイルはこのフォルダに入れようかな〜と思ってます。
私の少ない語彙で考えた結果、functionになってしまいました。もうちょっといい名前がありそう。

discord_bot/
ディスコードボットくん関連はここに入れてます。
バックアップのファイル(msdis.py.bak)は、更新したdiscordpyのバージョンだと動かないため削除しました。

google_drive/
ドライブ関連を入れてます。
複製と復元、その操作をするためのマウント用フォルダ、その他ちょっとだけ追加しました。
今回のファイル移動で色々不備が見つかったので、新規ファイルを作成しました。詳細は後々記載していきます。

大体こんな感じになってます。
とりあえず役割別で分けたんだな〜ってくらいで、大したことはしてないのでスルーしても大丈夫です。

掃除をするには掃除道具が必要

サービスサービスゥ!!

ここまでガンスルーしてきましたが、serviceファイルはなんでこっちきたねーんって話です。まあ以前の記事にも書いてるんですけどね。一応ね。
/etc/systemd/system/フォルダに作成してましたが、こいつだけアドレス違うのずるくな〜い??ていうか編集するファイルはできるだけまとめておきたいよねってことで移動させました。

でもでも〜!結局/etc/systemd/system/フォルダ内にあるserviceファイルしか認識されなくな〜い??バカなの??って方もいると思います。
こんなとき使えるのが、シンボリックリンクってやつです。

説明しよう!シンボリックリンクとは!

シンボリックリンクとは、オペレーティングシステム(OS)のファイルシステムの機能の一つで、特定のファイルやディレクトリを指し示す別のファイルを作成し、それを通じて本体を参照できるようにする仕組み。

『IT用語辞典 e-Words』より引用

つまり別の場所から参照できるというか、実質的に複数ヶ所に存在できるというか……。そういうことです。
(Windowsで言うショートカット的なイメージ?)
偉そうなこと言ってますが、あんまりよくわかってません。まあできりゃいいんすよ、できりゃ。

シンボリックリンクの使用方法は、こんな感じになります。
例)server_function/minecraft_server.serviceのシンボリックリンクを/etc/systemd/system/に作成する場合

sudo ln -s /home/ubuntu/minecraft_server/server_function/minecraft_server.service /etc/systemd/system/minecraft_service.service

これでシンボリックリンクにより、/etc/systemd/system/にもminecraft_server.serviceが適応されます。
あくまでマスターファイルはserver_function/minecraft_server.serviceなので、こっちを編集するとリンク先にも適宜適応されていきます。

とりあえずserviceファイルを作成したら、/etc/systemd/system/にシンボリックリンクを必ず適応しよう!ってお話です。

What time is it

今まで時間を初期設定の協定世界時(UTC)で使っていましたが、そろそろ日本標準時(JST)に合わせようということで変更手順を記載しておきます。

sudo timedatectl set-timezone Asia/Tokyo

たったこれだけ!?
これをやるだけなのに今まで放置してきたと……。
言い訳しておくと、プロキシ環境でraspbianを使ってた名残でめんどくさいと勘違いしてました。Ubuntuはかんたんなのね……ヨヨヨ

もちろん時間が変われば、時間を使用した設定も変わる。元気ですかーーーー!!!
ということでcrontabを編集していきます。

sudo crontab -e
0 12 * * *  /sbin/reboot
crontab -e
0 0 1 * * bash /home/ubuntu/minecraft_server/google_drive/drive_backup.sh

上が毎日12時にRaspberryPiの再起動、下が毎月1日にサーバーデータのバックアップっていう話です。

俺バカだからわかんねぇけどよ……。実行ユーザーが違うとバックアップ動きません。
前回の記事ではここ間違えてるので気をつけてください。修正しろって?やれたらやるわ。

バックアップの時間も月末から月初に変更しました。
だって月末の24時と月初の0時おんなじだし……。
伴ってdrive_backup.shの中身も変更してます。
このあと記載してるので、しっかりみてけ〜〜!!

メイン・ドメイン・ドドメイン

ドメインを取得してサーバーアドレスを変更しました。
いままでグローバルip見せまくってたの怖くない??手の届く範囲までしか見せてないし大丈夫かっていう甘い判断です。

freenomとかいうサイトで取りました。
なんかちょっとあやし〜〜のは、無料なので目を瞑ってください。

freenomでは、アカウントを作成することで、1ヶ月から12ヶ月は、5つのTLDが無料で使えます。
そのTLDの1つが.cfとかいう名前で、minecraftのcとfやん!!と思って使ってます。

期限の14日前から更新でき、更新するとまた1〜12ヶ月は無料で使えます。
無料より怖いものはないらしいけど……大丈夫っしょ!!

とりあえずアカウントを作成して、ドメインを取得し、グローバルIPを適用してやればいいって感じです。(更新を忘れずに!)
詳しくは自分で調べてください。決してめんどくさいから説明しないわけではないです。

ファイルを見せたいだけなのに

ここからはちょっと細かくファイルごとで話していきます。
プログラムも載せるので、多分めちゃくちゃ長いです。
いちいちコピペしなくても、最後にダウンロードリンク貼っておきます。
自分の環境に合わせて、カスタマイズして使ってね!
別に二次配布、なんなら三次配布してもいいけど、そこまですごいものでもないか。

server_function編

server_start.sh
サーバーを起動するシェルです。

#!/bin/sh
screen -UAdms MinecraftServer java -Xms4G -Xmx6G -jar /home/ubuntu/minecraft_server/minecraft_data/server.jar nogui

server_stop.sh
サーバーを停止するシェルです。

#!/bin/sh
screen -S MinecraftServer -X stuff 'say server shutdown in 1 min.\015'
sleep 60s
screen -S MinecraftServer -X stuff 'save-all\015'
sleep 10s
screen -S MinecraftServer -X stuff 'stop\015'

server_save.sh
サーバーを保存するシェルです。

#!/bin/sh
screen -S MinecraftServer -X stuff 'save-all\015'
screen -S MinecraftServer -X stuff 'say world saved.\015'

server_update.sh
サーバーファイルの更新をするシェルです。
papermcのナンバリングは大型アップデート以外は連番になることに対応して、大型アップデートは自分で行わなければならないようにしています。
仕様変更等もあるので、このような形にしました。
あとは最新版のナンバリングを取得してからダウンロードするようにしました。

#!/bin/bash

IFS=$'\n'
cd ~/minecraft_server/minecraft_data/

for ((count=0; count<2; count++)); do
  version=(`tac server_version.txt`)

  ((version[0]++))

  if ((count==1)); then
    ((version[1]++))
  fi

  versions=${version[3]}.${version[2]}
  if ((version[1]!=0)); then
    versions=$versions.${version[1]}
  fi
  number=${version[0]}

  paper_url='https://api.papermc.io/v2/projects/paper/versions/$versions/builds/$number/downloads/paper-$versions-$number.jar'

  eval curl $paper_url -f

  if [ $? != 22 ]; then

cat > server_version.txt << EOF
${version[3]}
${version[2]}
${version[1]}
${version[0]}
EOF

    count=-1
  fi
done

eval wget $paper_url

mv paper-$versions-$number.jar server.jar

cd ~/minecraft_server/minecraft_data/plugins/

geyser_url='https://ci.opencollab.dev//job/GeyserMC/job/Geyser/job/master/lastSuccessfulBuild/artifact/bootstrap/spigot/build/libs/Geyser-Spigot.jar'
floodgate_url='https://ci.opencollab.dev//job/GeyserMC/job/Floodgate/job/master/lastSuccessfulBuild/artifact/spigot/build/libs/floodgate-spigot.jar'

eval wget $geyser_url
eval wget $floodgate_url

mv Geyser-Spigot.jar.1 Geyser-Spigot.jar
mv floodgate-spigot.jar.1 floodgate-spigot.jar

minecraft_server.service
サーバーの起動と停止を行うサービスです。

[Unit]
Description=Minecraft Server Service
After=network.target

[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/minecraft_server/minecraft_data/
ExecStart=/home/ubuntu/minecraft_server/server_function/server_start.sh
ExecStop=/home/ubuntu/minecraft_server/server_function/server_stop.sh
Restart=always

[Install]
WantedBy=multi-user.target

minecraft_server_save.service
サーバーの保存を行うサービスです。

[Unit]
Description=Minecraft Server Save Service
After=network.target

[Service]
Type=simple
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/minecraft_server/minecraft_data/
ExecStart=/home/ubuntu/minecraft_server/server_function/server_save.sh

[Install]
WantedBy=multi-user.target

minecraft_server_update.service
サーバーファイルを更新するサービスです。

[Unit]
Description=Minecraft Server Update Service
After=network.target

[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/minecraft_server/minecraft_data/
ExecStart=/home/ubuntu/minecraft_server/server_function/server_update.sh
Restart=simple

[Install]
WantedBy=multi-user.target

保存後、以下コマンドを実行し、ラズパイ起動時に動作させる。

sudo systemctl enable minecraft_server_update.service

discord_bot篇

bot_start.sh
discord botを起動するシェルです。

#!/bin/sh
screen -UAmdS MinecraftBot python3 /home/ubuntu/minecraft_server/discord_bot/bot_minecraft.py

bot_stop.sh
discord botを停止するシェルです。
手打ちで動作を止める際のみ使用するので、なくても中のコマンドを打てば大丈夫です。

#!/bin/sh
sudo systemctl stop minecraft_server_bot.service

bot_minecraft.py
discord botの中身です。
TOKENには、各々のbotのTOKENを入れましょう。

import discord
from discord.ext import commands
import os
import time

TOKEN = 'WH1TEY0URD15C0RDB0TT0KEN'

bot = commands.Bot(command_prefix = '!', intents = discord.Intents.all())

@bot.event
async def on_ready():
    print('ログインしました')

@bot.command()
async def command(ctx):
    file = open('bot_command.txt', 'r')
    txt = file.read()
    await ctx.send(txt)
    file.close()

@bot.command()
async def start(ctx):
    if os.system('systemctl is-active minecraft_server.service') == 0:
        await ctx.send('Server - OPEN')
    else :
        await ctx.send('wait a minute...')
        os.system('sudo systemctl start minecraft_server.service')
        time.sleep(120)
        await ctx.send('Server - OPEN')

@bot.command()
async def stop(ctx):
    if os.system('systemctl is-active minecraft_server.service') == 0:
        await ctx.send('wait a minute...')
        os.system('sudo systemctl stop minecraft_server.service')
        time.sleep(90)
        await ctx.send('Server - CLOSE')
    else :
        await ctx.send('Server - CLOSE')

@bot.command()
async def save(ctx):
    if os.system('systemctl is-active minecraft_server.service') == 0:
        os.system('sudo systemctl start minecraft_server_save.service')
        await ctx.send('world saved.')
    else :
        await ctx.send('Server - CLOSE')

@bot.command()
async def status(ctx):
    if os.system('systemctl is-active minecraft_server.service') == 0:
        await ctx.send('Server - OPEN')
    else :
        await ctx.send('Server - CLOSE')

bot.run(TOKEN)

bot_command.txt
discord botの!commandコマンドで表示する内容。

!command - コマンド表示
!start   - サーバー起動
!stop    - サーバー停止
!save    - ワールド保存
!status  - サーバー状況

minecraft_server_bot.service
discord botを起動、停止するサービスです。

[Unit]
Description=Minecraft Server Bot Service
After=minecraft_server_update.service

[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/minecraft_server/discord_bot/
ExecStart=/home/ubuntu/minecraft_server/discord_bot/bot_start.sh
Restart=simple

[Install]
WantedBy=multi-user.target

google_drive変

drive_start.sh
google driveをマウントするシェルです。
前回は常にマウントを行う形で記載してましたが、長時間マウントをすると繋がらなくなる現象が起こるようなので、適宜呼び出してマウントすることにしました。

#!/bin/bash
google-drive-ocamlfuse ~/minecraft_server/google_drive/drive_mount

drive_stop.sh
google driveをアンマウントするシェルです。
アンマウントせずに再起動等を行うとエラーが発生する可能性があるので、上記のマウントで操作を行ったあとにアンマウントするようにしました。

#!/bin/bash
fusermount -u /home/ubuntu/minecraft_server/google_drive/drive_mount

drive_backup.sh
google driveへサーバーを複製するシェルです。
上記のマウントとアンマウントを行う文を追加しました。
複製する時間が月末から月初へ変更になったので、それに合わせて作成、削除するディレクトリ名を変更しました。
必要なpluginsフォルダの中身だけ複製していましたが、pluginsフォルダをそのまま複製しても容量がほとんど変わらないため、簡易的に記載しました。

#!/bin/bash
~/minecraft_server/discord_bot/bot_stop.sh
~/minecraft_server/server_function/server_stop.sh

sudo systemctl start minecraft_server_drive

new_directory=`date -d "1 month ago" '+%y.%m'`
delete_directory=`date -d "13 month ago" '+%y.%m'`

source_directory=~/minecraft_server/minecraft_data/
backup_directory=~/minecraft_server/google_drive/drive_mount/backup/

copy_data_array=("world" "world_nether" "world_the_end" "plugins" "server.jar" "server_version.txt")

mkdir $backup_directory$new_directory

for copy_data in ${copy_data_array[@]};do
    cp $source_directory$copy_data $backup_directory$new_directory -r
done

if [ -d $backup_directory$delete_directory ]; then
    rm $backup_directory$delete_directory -r
fi

sudo systemctl stop minecraft_server_drive

sudo reboot

drive_restore.sh
google driveから復元するシェルです。
上記の復元と同じように変更しました。

#!/bin/bash
source_directory=~/minecraft_server/minecraft_data/
backup_directory=~/minecraft_server/google_drive/drive_mount/backup/

backup_directory_name=before_restore

read -p "restore directory name:" restore_directory_name

if [ ! -d $backup_directory$restore_directory_name ]; then
    echo $restore_directory_name directory does not exist.
fi

if [ -d $backup_directory$restore_directory_name ]; then
    ~/minecraft_server/discord_bot/bot_stop.sh
    ~/minecraft_server/server_function/server_stop.sh

    sudo systemctl start minecraft_server_drive

    copy_data_array=("world" "world_nether" "world_the_end" "plugins" "server.jar" "server_version.txt")

    if [ $backup_directory_name != $restore_directory_name ]; then
        for copy_data in ${copy_data_array[@]};do
            cp $source_directory$copy_data $backup_directory$backup_directory_name -r
        done
    fi

    for copy_data in ${copy_data_array[@]};do
        cp $backup_directory$restore_directory_name$copy_data $source_directory -r
    done

    sudo systemctl stop minecraft_server_drive

    sudo reboot
fi

minecraft_server_drive.service
google driveをマウント、アンマウントするサービスです。

[Unit]
Description=Minecraft Server Drive Service
After=network.target

[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/minecraft_server/google_drive/
ExecStart=/home/ubuntu/minecraft_server/google_drive/drive_start.sh
ExecStop=/home/ubuntu/minecraft_server/google_drive/drive_stop.sh
Restart=always

[Install]
WantedBy=multi-user.target

ダウンロード

これまでのフォルダ(server_function / discord_bot / google_drive)を公開します。
ダウンロードするだけですぐ使えるわけじゃなく、.shや.pyの権限変更(chmod)や各自環境での内容変更、ポートを開放したりサーバーを起動したりしないと動作しません。試してないですけど。
詳しくは書く気がないので、過去の記事を確認してください。

一応備忘録的に書いておくと、scpコマンドでssh先からコピーすることができました(逆も可)。

後書き

終わってみればそこまで長くないかといった印象。
内容は少なかったはずなのに、書き終わるまで結構かかりました。
ドライブが理想通りの動作をしないのが悪い。

まとめてみて、色々やったなあと思いました。(小並感)
サーバーぶっ壊しという前科持ちの私のために書き始めましたが、この記事があれば、もうぶっ壊しても大丈夫だな!!!って感じのきゅうおさです。
ぶっ壊す前のサーバーなんて、毎日再起動するだけの最低限なものでしたが、今ではBotで操作できたり、統合版と遊べたり、ドライブにバックアップされてます!!歴史を感じる。
これからも機能やらなんやらを思いついたら、追加していきます。

実際に私と同じ環境を構築している人は流石にいなさそうですが、細かい所で役に立ってたり立ってなかったり……してるといいな!!!
正直かなりモチベになってるので、他の記事も見てくれるとうれぴよです。
冷やかしでもいいからみてくれ〜〜!!

基本形はこれでおわりかなと思います。
まあでも、時代とともに色々変わっていくのでね。
現時点ではできてますが、できなくなることもあると思います。
なんか更新内容だったりやりたいことがあれば、記事書くのでみてくれよな!!
とりあえず次回の内容は決まっているので、ぼちぼち出していきます。
それでは!

参考資料