1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Minecraft Education Dedicated Serverを1.20.133から1.26.32へUpdateした話

1
Posted at

はじめに

これまで、Minecraft Education Dedicated Serverを常時稼働で動かしていた。

バックアップも毎日取れるし。

ある日、連絡が来た。

「サーバーが古いから参加できません」

……はい?

調べてみると、原因はクライアントとDedicated Serverのバージョン不一致。

その結果、

PF Ver
Windowsユーザー 26.32
Macユーザー 20.133
Dedicated Server 20.133

という状態が発生。

当然、Windowsだけ接続できない。

「サーバー古いです」

という報告が上がってきた。

これは困る。解散の危機じゃん。

これ、今後も絶対に発生するやつだ。

ということで、今回はMinecraft Education Dedicated Serverを更新しつつ、今後のアップデートを楽にするスクリプトも作ることにした。


まず結論。

サーバの更新スクリプトを作ったので、これでサーバをUpdateする。
スクリプトは後半に全文記載。

./update-minecraft.sh --dryrun1

で新バージョンをDLが問題なければ、

サーバを止めてから

./update-minecraft.sh

で更新。

その後、手動でサーバーを起動。

以上。


今回のアプデ、何が変わるの?

今回更新したのは Minecraft Education v1.26.32.0。

公式の変更内容はこちら。

かなり大きなアップデートだった。

ざっくり4つ。

1. Dedicated Serverが大幅強化

今回、サーバー運用的に一番気になるのがこれ。

cross-tenant multiplayerに対応。

違う学校とか組織の間でも、同じサーバーでマルチプレイができるようになった。

公式が想定しているユースケースも面白い。

  • 別々の教室
  • 学校・地区をまたいだ共同プロジェクト
  • eスポーツ

など。

Minecraft EducationのDedicated Serverを、

学校A
  │
  │
  ├──── Dedicated Server ────┐
  │                           │
学校B                       │
  │                           │
  └───────────────────────────┘

という形で利用しやすくなる。

複数の組織で合同でマイクラやるなら、神アプデかも。

2. Bedrock側の新機能が大量に入った

今回のMinecraft Educationは、Bedrock Edition側の大型アップデートを取り込んでいる。

Bedrock Edition 1.21.131 → 1.26.30の主要アップデート込み。

Name Tag

クラフト可能なName Tagが追加。

これまでより簡単に、

  • Mobの名前付け
  • NPCの管理
  • チーム分け
  • ストーリー設定
  • 授業用ワールドの整理

などができる。

こういう細かい機能が、ワールド作るときに地味に効いてくる。

3. Tiny Takeover

Baby Mob関連の要素が追加された。

  • Baby Mob
  • Babyを生成するSpawn Egg
  • Golden Dandelion

など。

マイクラの中で、生き物の成長とか生態系を観察する授業とかに使えそう。

4. Chaos Cubed / Sulfur

そして今回の目玉のひとつ。

Sulfur(硫黄)関連の新要素。

新しい環境として、

  • Sulfur Caves
  • Sulfur Springs

新しいブロック・素材として、

  • Sulfur
  • Cinnabar

さらに、

  • Geyser
  • Sulfur Spikes
  • Sulfur Cube

などが追加されている。

これ、理科の実験とかに最高じゃん。

  • 地球科学
  • 化学
  • 環境システム

といったテーマにMinecraftを使える。

また一段と、学校の教材っぽさが増した感じ。


サーバーを手動で上げるのはだるい

で、本題のサーバー更新。

Minecraft Educationの公式手順では、既存のサーバーを新しくする場合、

  1. 最新版サーバーをダウンロード
  2. 新しいディレクトリへ展開
  3. 古いサーバーを停止
  4. 必要なファイルを新サーバーへコピー
  5. 新しいサーバーを起動

という手順になっている。

公式の更新手順はこちら。

移行するものは、

edu_server_session.json
worlds/
server.properties
allowlist.json
permissions.json

さらに、自分で追加・変更したリソースパックやビヘイビアーパックなども移行。

起動後はコンソールの、

Version: 1.26.32.0

という表示でバージョンを確認。

以上をスクリプトで自動化する

サーバー停止を確認

↓

最新版ダウンロード

↓

展開

↓

worldsとか設定ファイルを全部自動コピー

↓

カスタムファイル確認

↓

古いサーバーをまるごと自動バックアップ

↓

新サーバーへガッと置き換え

少しだけ技術的なノウハウ紹介。

  • あえて「サーバー起動・停止」は自動化しない
    アプデの途中で勝手にサーバーが動き出したり、止めるのに失敗したままデータ上書きして壊れるのが一番怖いから。そこは人間の目で確認する。
  • dryrun機能
    いきなり本番環境が書き換わるのは怖いから、ダウンロードと展開チェックだけやるモードを作った。

使い方はこんな感じ。

まずはテスト。

./update-minecraft.sh --dryrun1

これを実行すると、最新版を勝手に取ってきて、一時フォルダで解凍して、中身が壊れてないかチェックするところまでやってくれる。

最新版をダウンロード
       ↓
ZIPを検証
       ↓
一時ディレクトリへ展開
       ↓
bedrock_serverを確認
       ↓
終了

既存のサーバーフォルダは一切触らないから安全。

テストがOKなら、本番サーバーを一旦自分で止めてから、通常アップデートを実行。

./update-minecraft.sh

これで、さっきのコピペ作業からバックアップまで一瞬で終わる。

プロセス確認
    ↓
最新版ダウンロード
    ↓
一時ディレクトリへ展開
    ↓
bedrock_server確認
    ↓
設定ファイル移行
    ↓
worlds移行
    ↓
カスタムファイル移行
    ↓
再度プロセス確認(念のため)
    ↓
バックアップ作成
    ↓
/opt/minecraftをガバッと更新
    ↓
終了

終わったら、いつもの手順でサーバーをポチッと起動するだけ。

まとめ

これで次から「サーバーが古くて入れませーん」って言われても、白目を剥かずに真顔でスクリプト叩くだけで解決できるようになった。自動化最高。

よーし、アプデも無事に終わったし、新要素の「Sulfur Caves(硫黄の洞窟)」とかいうやつをみんなで見に行くぞ!ってなって、ウキウキでサーバーを起動した。

サーバーログにもバッチリ Version: 1.26.32.0 の文字。完璧。

さあ、Windowsのやつら、入れなくて文句言ってたキッズたち、早く入ってこい!

……って待ってたんだけど、誰も入ってこない。

「入れないんですけど」ってまたチャットが来た。

え?なんで?サーバーは最新だよ?

Macは手動でUpdateしないとだめみたい。マイクラはWindowsがオススメでした・・・

付録 アプデ用スクリプト

アプデ用スクリプトは、長いので折りたたんで置いておく。

update-minecraft.sh

使うときは、スクリプト内の SERVER_DIR="/opt/minecraft" とかのパスを自分の環境に合わせて書き換えてね。

#!/bin/bash

set -euo pipefail

# ============================================================
# Minecraft Education Dedicated Server Update
#
# Usage:
#
#   ./update-minecraft.sh --dryrun1
#   ./update-minecraft.sh
#
# --dryrun1:
#   最新版をDLして一時ディレクトリへ展開
#   /opt/minecraftは変更しない
#
# 通常モード:
#   プロセス確認
#   最新版をDL
#   一時ディレクトリへ展開
#   設定・worldsを移行
#   現在のサーバーをバックアップ
#   /opt/minecraftを新版へ置換
#
# IMPORTANT:
#   Minecraftの停止・起動は行わない
#   sudo/rootは使用しない
# ============================================================

SERVER_DIR="/opt/minecraft"

DOWNLOAD_URL="https://aka.ms/downloadmee-linuxserver"

PROCESS_NAME="bedrock_server_edu"

TIMESTAMP=$(date +"%Y%m%d_%H%M%S")

WORK_DIR="/tmp/minecraft-update-${TIMESTAMP}"

NEW_DIR="${WORK_DIR}/minecraft"

ZIP_FILE="${WORK_DIR}/server.zip"

BACKUP_DIR="${HOME}/minecraft-backup-${TIMESTAMP}"


# ============================================================
# Functions
# ============================================================

error()
{
    echo
    echo "ERROR: $1"
    echo
    exit 1
}


cleanup()
{
    if [ -d "$WORK_DIR" ]; then
        echo
        echo "作業ディレクトリ:"
        echo "  ${WORK_DIR}"
    fi
}

trap cleanup EXIT


# ============================================================
# Argument
# ============================================================

MODE="${1:-normal}"

case "$MODE" in

    --dryrun1)
        DRYRUN1=true
        ;;

    normal)
        DRYRUN1=false
        ;;

    *)
        error "Unknown option: ${MODE}

使用方法:

  $0
  $0 --dryrun1"

        ;;

esac


# ============================================================
# Check commands
# ============================================================

for CMD in curl unzip rsync find pgrep ps stat mv mkdir chmod; do

    if ! command -v "$CMD" >/dev/null 2>&1; then
        error "${CMD} が見つかりません"
    fi

done


# ============================================================
# Header
# ============================================================

echo "=============================================="
echo " Minecraft Education Dedicated Server"
echo "=============================================="
echo

echo "User:"
echo "  $(whoami)"

echo

if [ "$DRYRUN1" = true ]; then

    echo "Mode:"
    echo "  DRYRUN1"

else

    echo "Mode:"
    echo "  UPDATE"

fi

echo


# ============================================================
# DRYRUN1
# ============================================================

if [ "$DRYRUN1" = true ]; then

    echo "=============================================="
    echo " DRYRUN1"
    echo "=============================================="
    echo

    echo "実行内容:"
    echo
    echo "  ✓ 最新版をダウンロード"
    echo "  ✓ ZIPを検証"
    echo "  ✓ 一時ディレクトリへ展開"
    echo "  ✓ bedrock_server確認"
    echo
    echo "実行しない処理:"
    echo
    echo "  × Minecraft停止"
    echo "  × Minecraft起動"
    echo "  × /opt/minecraft変更"
    echo "  × worlds移行"
    echo "  × 設定移行"
    echo "  × バックアップ"
    echo


    mkdir -p "$NEW_DIR"

    echo "[1/4] 最新版をダウンロード"

    curl \
        -fL \
        --retry 3 \
        --retry-delay 2 \
        "$DOWNLOAD_URL" \
        -o "$ZIP_FILE"


    echo
    echo "[2/4] ZIPを検証"

    unzip -t "$ZIP_FILE" >/dev/null

    echo "  OK"


    echo
    echo "[3/4] ZIPを展開"

    unzip -q "$ZIP_FILE" -d "$NEW_DIR"


    echo
    echo "[4/4] bedrock_serverを確認"

    BEDROCK_SERVER=""

    if [ -f "${NEW_DIR}/bedrock_server_edu" ]; then

        BEDROCK_SERVER="${NEW_DIR}/bedrock_server_edu"

    else

        BEDROCK_SERVER=$(
            find "$NEW_DIR" \
                -type f \
                -name "bedrock_server_edu" \
                -print -quit
        )

    fi


    if [ -z "$BEDROCK_SERVER" ]; then

        error "bedrock_serverが見つかりません"

    fi


    #chmod +x "$BEDROCK_SERVER"


    echo
    echo "=============================================="
    echo " DRYRUN1 completed"
    echo "=============================================="
    echo

    echo "展開先:"
    echo "  ${NEW_DIR}"

    echo
    echo "bedrock_server:"
    echo "  ${BEDROCK_SERVER}"

    echo
    echo "既存の /opt/minecraft は変更していません。"
    echo

    exit 0

fi


# ============================================================
# Normal mode
# ============================================================

echo "=============================================="
echo " UPDATE"
echo "=============================================="
echo


# ============================================================
# Check /opt/minecraft
# ============================================================

echo "[1] 現在のサーバーを確認"

if [ ! -d "$SERVER_DIR" ]; then

    error "${SERVER_DIR} が存在しません"

fi


if [ ! -f "${SERVER_DIR}/bedrock_server_edu" ]; then

    error "${SERVER_DIR}/bedrock_server が見つかりません"

fi


# ============================================================
# Check write permission
# ============================================================

echo
echo "[2] 書き込み権限を確認"

if [ ! -w "$SERVER_DIR" ]; then

    error "${SERVER_DIR} に書き込み権限がありません。

現在の権限:

$(ls -ld "$SERVER_DIR")

実行ユーザー:
$(whoami)"

fi

echo "  OK"


# ============================================================
# Check Minecraft process
# ============================================================

echo
echo "[3] Minecraftプロセスを確認"

PIDS=$(pgrep -x "$PROCESS_NAME" || true)

if [ -n "$PIDS" ]; then

    echo
    echo "ERROR: Minecraft Serverが起動しています。"
    echo

    echo "PID:"
    echo "$PIDS"

    echo
    echo "Process:"
    ps -fp $PIDS

    echo
    echo "Minecraftを停止してから再実行してください。"

    exit 1

fi

echo "  OK: ${PROCESS_NAME} は停止しています"


# ============================================================
# Check owner
# ============================================================

echo
echo "[4] 所有者を確認"

SERVER_OWNER=$(stat -c '%U' "$SERVER_DIR")
SERVER_GROUP=$(stat -c '%G' "$SERVER_DIR")

echo
echo "Server:"
echo "  ${SERVER_DIR}"

echo
echo "Owner:"
echo "  ${SERVER_OWNER}:${SERVER_GROUP}"


# ============================================================
# Create work directory
# ============================================================

echo
echo "[5] 一時ディレクトリを作成"

mkdir -p "$NEW_DIR"


# ============================================================
# Download
# ============================================================

echo
echo "[6] 最新版をダウンロード"

curl \
    -fL \
    --retry 3 \
    --retry-delay 2 \
    "$DOWNLOAD_URL" \
    -o "$ZIP_FILE"


# ============================================================
# Verify ZIP
# ============================================================

echo
echo "[7] ZIPを検証"

unzip -t "$ZIP_FILE" >/dev/null

echo "  ZIP OK"


# ============================================================
# Extract
# ============================================================

echo
echo "[8] 最新版を展開"

unzip -q "$ZIP_FILE" -d "$NEW_DIR"


# ============================================================
# Find bedrock_server
# ============================================================

echo
echo "[9] bedrock_serverを確認"

BEDROCK_SERVER=""

if [ -f "${NEW_DIR}/bedrock_server_edu" ]; then

    BEDROCK_SERVER="${NEW_DIR}/bedrock_server_edu"

else

    BEDROCK_SERVER=$(
        find "$NEW_DIR" \
            -type f \
            -name "bedrock_server_edu" \
            -print -quit
    )

fi


if [ -z "$BEDROCK_SERVER" ]; then

    error "bedrock_serverが見つかりません"

fi


chmod +x "$BEDROCK_SERVER"

echo "  ${BEDROCK_SERVER}"


# ============================================================
# Normalize extracted directory
# ============================================================

if [ "$BEDROCK_SERVER" != "${NEW_DIR}/bedrock_server_edu" ]; then

    echo
    echo "展開されたサブディレクトリを整理"

    EXTRACT_ROOT=$(dirname "$BEDROCK_SERVER")

    TEMP_ROOT="${WORK_DIR}/minecraft-root"

    mkdir -p "$TEMP_ROOT"

    rsync -a \
        "${EXTRACT_ROOT}/" \
        "${TEMP_ROOT}/"

    rm -rf "$NEW_DIR"

    mv "$TEMP_ROOT" "$NEW_DIR"

    BEDROCK_SERVER="${NEW_DIR}/bedrock_server_edu"

    chmod +x "$BEDROCK_SERVER"

fi


# ============================================================
# Copy official migration files
# ============================================================

echo
echo "[10] 設定を移行"

COPY_ITEMS=(
    "edu_server_session.json"
    "server.properties"
    "allowlist.json"
    "permissions.json"
)

for ITEM in "${COPY_ITEMS[@]}"; do

    if [ -e "${SERVER_DIR}/${ITEM}" ]; then

        echo "  Copy: ${ITEM}"

        rsync -a \
            "${SERVER_DIR}/${ITEM}" \
            "${NEW_DIR}/${ITEM}"

    fi

done


# ============================================================
# Copy worlds
# ============================================================

if [ -d "${SERVER_DIR}/worlds" ]; then

    echo
    echo "[11] worldsを移行"

    mkdir -p "${NEW_DIR}/worlds"

    rsync -a \
        "${SERVER_DIR}/worlds/" \
        "${NEW_DIR}/worlds/"

else

    echo
    echo "[11] worldsなし"

fi


# ============================================================
# Copy custom files
# ============================================================

echo
echo "[12] カスタムファイルを移行"

for ITEM in "${SERVER_DIR}"/*; do

    BASENAME=$(basename "$ITEM")

    case "$BASENAME" in

        bedrock_server)
            continue
            ;;

        server.properties)
            continue
            ;;

        allowlist.json)
            continue
            ;;

        permissions.json)
            continue
            ;;

        edu_server_session.json)
            continue
            ;;

        worlds)
            continue
            ;;

        logs)
            continue
            ;;

    esac


    if [ -e "${NEW_DIR}/${BASENAME}" ]; then

        echo "  Keep new version: ${BASENAME}"

    else

        echo "  Custom: ${BASENAME}"

        rsync -a \
            "$ITEM" \
            "${NEW_DIR}/"

    fi

done


# ============================================================
# Final process check
# ============================================================

echo
echo "[13] 更新直前のプロセス確認"

PIDS=$(pgrep -x "$PROCESS_NAME" || true)

if [ -n "$PIDS" ]; then

    error "Minecraft Serverが起動しました。更新を中止します。"

fi

echo "  OK"


# ============================================================
# Backup
# ============================================================

echo
echo "[14] 現在のサーバーをバックアップ"

mkdir -p "$BACKUP_DIR"

rsync -a \
    "${SERVER_DIR}/" \
    "${BACKUP_DIR}/"

echo
echo "Backup:"
echo "  ${BACKUP_DIR}"


# ============================================================
# Replace
# ============================================================

echo
echo "[15] /opt/minecraftを更新"

OLD_DIR="${WORK_DIR}/minecraft-old"

mv "$SERVER_DIR" "$OLD_DIR"

mv "$NEW_DIR" "$SERVER_DIR"


# ============================================================
# Result
# ============================================================

echo
echo "=============================================="
echo " UPDATE completed"
echo "=============================================="
echo

echo "Server:"
echo "  ${SERVER_DIR}"

echo
echo "Backup:"
echo "  ${BACKUP_DIR}"

echo
echo "Old server:"
echo "  ${OLD_DIR}"

echo
echo "Minecraft Serverは起動していません。"
echo "起動は外部から実施してください。"
echo

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?