見出し画像

GoogleDriveでMinecraftサーバーを管理しよう!!!!

前書き

マイクラサーバー記事の第四弾です。
是非、前回までの記事もご覧ください!

第一弾『Raspberry PiでMinecraftサーバーを構築しよう!』

第二弾『DiscordBotでMinecraftサーバーを動かそう!!』

第三弾『統合版でJava版Minecraftサーバーにログインしよう!!!』

前回サーバーを構築した際にはOSを誤って壊してしまい、OSごと初期化しないといけない様な事態になってしまいました💥💥💥
新しく構築しても前回までのワールドは残っておらず、新規でスタートする形になりました。
が、いかんせんプレイ人口は伸びません😢
マイクラ自体に流行り廃りの波があるので実はあまり関係はないのでは???とか思ってないけどね!!

なので今回はGoogleDriveにワールドデータをバックアップすることで、前回の様な事故があってもワールドを復活出来る様にします✨
久しぶりに記事を書くのでノリが分からん!!こんな感じだったか???

他にもちょこちょこ機能追加していきます!
ということで今回も見切り発車でやっていこ~~🚂=3ポッポー

用意する物

・Minecraftサーバーを起動できるRaspberry Pi
・PC(私はwin10)
・時間(できるだけたくさん)

ファイルのUpping to the date!!

サーバーのバージョンを上げるために、毎回公式サイトからダウンロードして名前変えて……っていうのがめんどくさかったので、自動化させました。
というか前回色々したついでに作ってました。
こういう自動化とかがプログラムの楽しいとこですよね!!!ね!!!!
papermc、geysermc、floodgateの3つをアップデートできるようにしていきますよ~😊

まずはpapermcから行きましょう。というかここが鬼門過ぎかも……。
アップデートするファイルはmcserver/server.jarで、ダウンロード先は以下URL。

ダウンロードのするURLの形は以下のようになっています。

https://api.papermc.io/v2/projects/paper/versions/1.19.2/builds/263/downloads/paper-1.19.2-263.jar

papermc 1.19.2 #263の場合

ここで大切なのはバージョンの番号(1.19.2#263)です!
新しいサーバーファイルが更新されたらこの番号だけ変更されていくので、しっかり対応していくためのプログラムが以下です。

#!/bin/bash

IFS=$'\n'
cd ~/mcserver

for ((i=0; i<4; i++)); do
  version=(`cat version.txt`)

  version[i]=$((version[i]+1))

  for ((j=i+1; j<4; j++)); do
    version[j]=0
  done

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

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

  eval wget $paper_url

  if [ $? == 0 ]; then
    mv paper-$versions-$number.jar server.jar

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

    let "i--"
  fi
done

こいつの名前はupdate.shとでもしておいてます。mcserverフォルダに入れておきましょう。

中身を簡単に説明すると、version.txtからバージョン番号を取得し、現在のバージョン+1をそれぞれの番号で調べ、それがダウンロードできた際にserver.jarに上書きし、version.txtにもバージョン番号を上書きする。
といったプログラムになっています。わかりにくっ!

version.txtは現在のバージョン番号が改行で分けられたもので、以下例。

1
19
2
263

まあとりあえずこれを実行するとsever.jarは最新版に更新されるってわけですよ……。へへ…….。

次に統合版のgeysermc、floodgateをアップデートしていくゥ!
こちらは最新版のURLが同じなので簡単でした。
以下をupdate.shに追記していきます。

cd ~/mcserver/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

こっちの方がわかりやすいですね~~全部こうしてくれよ!
こちらは同じ名前でファイルが入ってしまうので、ファイル名に付く.1を取り除くこと(上書き保存)が必要です。

update.shを実行するために以下も作成していきまちゅ。

[Unit]
Description=Jar Update
After=network.target

[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/mcserver/
ExecStart=/home/ubuntu/mcserver/update.sh
Restart=simple

[Install]
WantedBy=multi-user.target

こいつを/etc/systemd/system/jar.serviceとする。
起動時にupdate.shを実行するようにしましたが、一応サーバー起動と被ると怖いので、DiscordBotがjar.serviceの後に実行されるように、以下のようにdis.serviceも変更しておきます。

[Unit]
Description=Discord Bot
After=jar.service

[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/mcserver/
ExecStart=/home/ubuntu/mcserver/distart.sh
Restart=always

[Install]
WantedBy=multi-user.target

Afterの欄でスね。
あとは以下で、実行権限とか.serviceファイルの更新もしてあげましょうね。

chmod +x ~/mcserver/update.sh
sudo systemctl daemon-reload

そしたら再起動で、多分適応されると思われます。

これで毎回なんじゃかんじゃしなくて済みます。
ほんとはサイトが更新されたらとかやろうと思ってました。
が、めんどくさかったので止めました。
jar.serviceで我慢してやりますか……!

注意点としてたまに連番じゃない時があるので、自分でversion.txtを編集する必要があるっていうのと、version.txtを編集する際は最新の番号から1つ前の番号を保存する必要があります。(プログラムの性質上)

以下以下うるせー文章を見て頂きありがとうございます!
残念ながらここから本編です!!

データのBack to the up!!!

準備のための準備のための準備のための……

じゃあ早速ソフトを入れよう!としたんですが、ubuntu21.10からアップデートを行わないといけないようなので、やっちゃいます(笑)
最新のubuntu22.04にアップデートしていきます。

とりあえずsudo do-release-upgradeでアップデート!と思いきや、apt updateしてください!!って怒られました……
そんでapt updateやったらエラー!エラー!!!
なんか/etc/apt/sources.listがports.ubuntu.com/ubuntu-portsとかいう20.10の古いやつだからダメ!みたいなことになってるっぽいので以下で書き換えていきます。

sed -i -e 's/ports.ubuntu.com\/ubuntu-ports/old-releases.ubuntu.com\/ubuntu/g' /etc/apt/sources.list

やっとこapt updateできるようになったので以下以下。

sudo apt update
sudo apt upgrade
sudo do-release-upgrade

進んでいく中でcontinue?って言われたらy押して、please press [Enter]って言われたらEnter押しましょう。
軽い気持ちで始めたら結構時間かかってビビりました。
多分2時間くらいかかりますので、時間があるときにやりましょう。
僕は時間ないときにやったので最悪でした。
後から気づきましたが勢い余ってUbuntu22.10にアップデートしてました。
ダウングレードはできませんが22.04のものを入れて対応していきます。

これでうまくいくと思いきや、次はosをアップデートしたことでdiscordbotが起動しなくなったので、discord.pyの更新も行った。なんなら半分作り直した……。
以下でdiscord.pyも最新版に!

pip3 install discord.py

最新版だとなんだか書き方全然違うみたいなので、いろいろ調べてなんとか兆しが見えてきたら午前3時😊😊😊😊明日は遅刻かな😊😊😊😊😊
p.s.何とか遅刻5分前に間に合いました(もう夜更かししません許して……。)
ということで遅刻を乗り越えたので、以下イカ!!!

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

TOKEN = 'Jibunn0T0KENw0Iremash0u'

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

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

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

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

@bot.command()
async def stop(ctx):
    if os.system('systemctl is-active ms') == 0:
        await ctx.send('wait a minute...')
        os.system('sudo systemctl stop ms')
        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 ms') == 0:
        os.system('sudo systemctl start ms-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 ms') == 0:
        await ctx.send('Server - OPEN')
    else :
        await ctx.send('Server - CLOSE')

bot.run(TOKEN)

mcserver/msdis.pyの内容は処理層に変更はほとんどありませんが、discord.ext.commandsを入れてコマンドを管理するようになりました。
他にもちょこちょこ変更していきます。

[Unit]
Description=Discord Bot
After=jar.service

[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/mcserver/
ExecStart=/home/ubuntu/mcserver/distart.sh
Restart=simple

[Install]
WantedBy=multi-user.target

/etc/systemd/system/dis.serviceのRestart=simpleへ変更。

#!/bin/sh
screen -UAmdS Discord python3 /home/ubuntu/mcserver/msdis.py

mcserver/distart.shの実行権限をsudoからユーザーへ変更。
(これはファイルの作成方法による可能性大なので、変える必要がない場合もありそう。)

こんな感じで何とか戻りました……。
ただアップデートするだけだと思ったら、全体的にアップデートしなくちゃいけなくて大変……。
目についていないだけでアップデートが必要な箇所もありそうですが、見つかったら都度対応します……。

バックアップ・ルックバック・バックパック・キックバック

ということでほんへと言っても過言ではないワールドのバックアップを実装していく~~~!!!やっとか。

ほんじゃまず以下でソフトを入れてくぞ!!
それなりに時間かかりますので、気を付けて!

sudo dpkg --configure -a
sudo apt install software-properties-common dirmngr
sudo add-apt-repository ppa:alessandro-strada/ppa

よーく見るとここでports.ubuntu.comが入っていますね。
ここまでの努力の賜物を感じます。
どんどんいくじょ!!

sudo nano /etc/apt/sources.list.d/alessandro-strada-ubuntu-ppa-jammy.list

中身は以下に変更!

deb https://ppa.launchpadcontent.net/alessandro-strada/ppa/ubuntu/ jammy main
#deb-src https://ppa.launchpadcontent.net/alessandro-strada/ppa/ubuntu/ jammy main

以下!以下!!

apt-key adv --keyserver keyserver.ubuntu.com --recv-keys AD5F235DF639B041
apt update
apt install google-drive-ocamlfuse

これでエラーなければ入ったと思います。
osアップデートからソフト入れるまでにリアル3日かかりました……。

次はGoogle Driveにバックアップを取る際の、Googleのアカウントをつくってこい!話はそれからだ!!
ここからの操作はPCでやりましょう。

太郎君!保存頑張って!!てか標準で15GBも入るんすね~

そのアカウントで以下のURLにアクセスして設定していきます。

設定項目を箇条書きで書いてまいります。

選択:[] 記入:「」 ボックスにチェック:☑

・(初回起動時のみ)
 利用規約☑
 [同意して続行]

・[プロジェクトの選択▼]
  ↳[新しいプロジェクト]
    ↳プロジェクト名「backup project」
      [作成]
      ↳[プロジェクトの選択]
        ↳[backup project]

・[APIとサービス]
  ↳[+APIとサービスの有効化]
    ↳[Google Drive API]
      ↳[有効にする]

・[OAuth同意画面]
  ↳[作成]
    ↳アプリ名「backup application」
      ユーザーサポートメール「mail@example.com」
      
デベロッパーの連絡先情報「mail@example.com」
      [保存して次へ]
      ↳[スコープを追加または削除]
        ↳フィルタ「Google Drive API」
          全16項目☑
          [更新]
          ↳[保存して次へ]
            ↳[ADD USERS]
              ↳「mail@example.com」
                [追加]
                ↳[保存して次へ]
                  ↳[ダッシュボードに戻る]

・[認証情報]
  ↳[認証情報を追加]
    [OAuth クライアント ID]
    ↳[アプリケーションの種類]
      「デスクトップ アプリ」
      [作成]
      ↳[クライアント ID]コピー
        [クライアント シークレット]コピー
        [OK]

ほんとは画像を用意したかったけど個人情報映りそうなのでやめました

設定割と沢山ありますね~。
入力欄は編集して頂いても大丈夫です。
しっかり自分のメールアドレスを入力しましょうね。

またラズパイに戻ります。
以下っちょ!

google-drive-ocamlfuse -headless -id クライアントID -secret クライアントシークレット

先程コピーしたクライアントIDとクライアントシークレットを入れてくだちい。
そうすると以下が出力されます。

Please, open the following URL in a web browser: https://accounts.google.com/o/oauth2/auth?client_id=...
Please enter the verification code:

一行目の発行されたURLを踏んで、進めていきます。
この時先程、登録したメールアドレスでログインしていることが必要です。
許可を選択すると認証コードが発行されるので、二行目にコードを張り付けて実行します。

mkdir ~/gdrive
google-drive-ocamlfuse ~/gdrive

GoogleDrive用のフォルダを用意してマウントしてあげると、GoogleDriveと接続されます。
このフォルダを介してデータのやり取りをすることが出来ます!!!
出来てよかった……!!

google-drive-ocamlfuse ~/gdrive

色々いじってて気が付いたんですが、再起動するとフォルダのマウントが初期化してしまうので、.bashrcに↑のコマンドを追記します。

ドライブに保存するシェル書いてくぞ!

とりあえず全てがぶっ壊れたとき用に、最初は全部保存してもいいかなと思います。
後はワールドデータを継続的に保存していきます。
まずはバックアップ用のフォルダを作成します。

mkdir ~/gdrive/backup

backupフォルダに月ごとに分けて入れていきます。
必要なフォルダとファイルは全7個ってことにしておきます。
イカ。

#!/bin/bash

year=`date '+%y'`
month=`date '+%m'`

year_month=$year.$month
delete_year_month=$((year-1)).$month

~/mcserver/distop.sh
~/mcserver/stop.sh

mkdir ~/gdrive/backup/$year_month
mkdir ~/gdrive/backup/$year_month/plugins

cp ~/mcserver/world ~/gdrive/backup/$year_month -r
cp ~/mcserver/world_nether ~/gdrive/backup/$year_month -r
cp ~/mcserver/world_the_end ~/gdrive/backup/$year_month -r
cp ~/mcserver/server.jar ~/gdrive/backup/$year_month -r
cp ~/mcserver/plugins/Geyser-Spigot.jar ~/gdrive/backup/$year_month/plugins -r
cp ~/mcserver/plugins/floodgate-spigot.jar ~/gdrive/backup/$year_month/plugins -r
cp ~/mcserver/version.txt ~/gdrive/backup/$year_month -r

rm ~/gdrive/backup/$delete_year_month -r

sudo reboot

mcserver/backup.shとして保存します。
上三つのフォルダはワールドデータで、中三つのファイルは起動用jarで、下一つのファイルはバージョンのテキストです。

バックアップの際は、サーバーを起動しているとデータが破損する可能性があるのでサーバーを落とし、バックアップ作成中にサーバーを起動できないようにdiscordbotを切断しましょう。

ドライブに無限にデータが入るわけではないので、1年前のバックアップは消すようにします。

いろいろ入ってますね…

バックアップは取れましたと……。
毎月末に実行するため、以下をcrontabに追記します。

0 15 28-31 * * /usr/bin/test $(date -d '+1 day' +%d) -eq 1 && bash ~/mcserver/backup.sh

月末の日本時間で0時にバックアップをします。

じゃあ逆にリストア(復元)するためのシェルも作りますか……。もうちゅかれた……。
はいはい、いかいか。

#!/bin/bash

read -p "backup directory name:" year_month

if [ ! -d ~/gdrive/backup/$year_month ]; then
    echo $year_month directory does not exist.
fi

if [ -d ~/gdrive/backup/$year_month ]; then
    backup_file=before_restore

    ~/mcserver/distop.sh
    ~/mcserver/stop.sh

    if [ $backup_file != $year_month ]; then
        echo backup
        cp ~/mcserver/world ~/gdrive/backup/$backup_file -r
        cp ~/mcserver/world_nether ~/gdrive/backup/$backup_file -r
        cp ~/mcserver/world_the_end ~/gdrive/backup/$backup_file -r
        cp ~/mcserver/server.jar ~/gdrive/backup/$backup_file -r
        cp ~/mcserver/plugins/Geyser-Spigot.jar ~/gdrive/backup/$backup_file/plugins -r
        cp ~/mcserver/plugins/floodgate-spigot.jar ~/gdrive/backup/$backup_file/plugins -r
        cp ~/mcserver/version.txt ~/gdrive/backup/$backup_file -r
    fi

    echo restore
    cp ~/gdrive/backup/$year_month/world  ~/mcserver -r
    cp ~/gdrive/backup/$year_month/world_nether ~/mcserver -r
    cp ~/gdrive/backup/$year_month/world_the_end ~/mcserver -r
    cp ~/gdrive/backup/$year_month/server.jar ~/mcserver -r
    cp ~/gdrive/backup/$year_month/plugins/Geyser-Spigot.jar ~/mcserver/plugins -r
    cp ~/gdrive/backup/$year_month/plugins/floodgate-spigot.jar ~/mcserver/plugins -r
    cp ~/gdrive/backup/$year_month/version.txt ~/mcserver -r

    sudo reboot
fi

mcserver/restore.shとして保存していく。
backupファイルに入っているフォルダ名を入力することで、直前のフォルダをバックアップして、指定したフォルダにあるデータをmcserverに呼び出せるってわけですな。
こいつを使うために直前バックアップ用のフォルダを作成しておきます。

mkdir ~/gdrive/backup/before_restore
mkdir ~/gdrive/backup/before_restore/plugins

バックアップを取ってからリストアするので、かなり時間がかかります。
大体1時間くらいかかりました。
自動再起動を入れている方は、リストアする時間に気を付けて行いましょう。

実際にバックアップとリストアを試してみよう!!
バックアップを取るデータがイカの画像になります。

鉄の魔人です

バックアップ後のデータが以下です。

鉄の壁になっちゃった!!

リストア後のワールドが以下です。

鉄の魔人に戻ってよかった~~!

今回はこの辺にしといてやるわ!!!じゃあな!!!!
ま~じで疲れたんでこの辺で許してやってください……。

後書き

実はラズパイの消費電力を減らす長期運用設定とやらもしようと思っていたのですが、知識不足で実装に至りませんでした。くやしーー!!
HDMIやWifiの無線、Bluetooth等を切ることができるようです。
あまり設定方法がわからなかったし、調べると消費電力がそもそも少ないから別にやらなくても大丈夫そうなので、実装予定ないです。

一つここで注意喚起をしておくと、私はアホなのでSSHで外部から接続中にrebootではなくshutdownコマンドで落としてしまいました。アホなので。
皆さんはこのようなことがないよう日頃からrebootコマンドを使用しましょうね……。

というか今回実装するまでの時間が長すぎ!!!!
マジで1週間暇さえあればいじって、やっとこ終わったことにしました……。
正直プログラムはだいぶ雑に書いているので、納得いってないところがおおいです。
もっといじるべきところもたくさんありますが、放っておいてもなんか動いてるのでとりあえずよしってことで。

一応最初に思い描いていた部分まで実装が終わったので、次回の記事はこれまでのまとめというか整理したものを出します。
総集編ってやつです。
手癖で書いてるからファイル名や変数名等がわかり肉すぎる。

なんだかんだで改良も加えると思うので、次回もぜひ見てくれよな!!

参考資料

ファイルのUpping to the date!!

データのBack to the up!!!