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 Paperサーバー管理スクリプト: mc_backup.sh の詳細解説

Last updated at Posted at 2025-08-16

本記事は Gemini CLI の YOLO mode で出力された内容です。

はじめに

本稿では、Minecraft Paperサーバーの運用を効率化するためのシェルスクリプト mc_backup.sh について詳細に解説します。このスクリプトは、サーバーの新規セットアップ、既存ワールドデータの更新、およびバックアップからのワールド復元といった一連のプロセスを自動化し、サーバー管理者の負担を軽減することを目的としています。

環境

  • OS: Linux (Debian GNU/Linux 13 trixie)
  • Gemini CLI バージョン: 0.1.21
  • 作業ディレクトリ: $HOME/gemini_workspace

スクリプトの概要と機能

mc_backup.sh は、以下の主要な機能を提供します。

  1. 既存ワールドデータからの新規セットアップ(更新モード):
    • 既に稼働中のMinecraftサーバーのワールドデータが存在する場合、そのデータを使用して新しいサーバー環境を構築します。これにより、既存の進捗を維持したまま、新しいサーバーバージョンやプラグイン環境への移行が容易になります。
  2. バックアップからのワールド復元(復元モード):
    • 既存のワールドデータが見つからない場合、事前に作成されたバックアップZIPファイルの一覧から選択し、指定されたワールドデータを復元します。これにより、予期せぬデータ損失からの回復や、過去の特定時点のワールドへのロールバックが可能になります。
  3. 自動バックアップとクリーンアップ:
    • 既存ワールドデータを使用して更新モードを実行する際、現在のワールドデータを自動的にバックアップします。
    • 新しいサーバー環境のセットアップ後、古いサーバーディレクトリを自動的に指定されたクリーンアップディレクトリへ移動し、ディスクスペースの整理を支援します。
  4. start_minecraft.sh の自動更新:
    • スクリプトの実行後、常に最新のサーバーインスタンスを起動するための補助スクリプト start_minecraft.sh を自動的に更新します。

スクリプトは、復元可能なバックアップZIPファイルも、更新可能な既存のワールドデータも見つからない場合には、エラーメッセージを出力して終了します。

必須ディレクトリとファイル構造

mc_backup.sh を実行するにあたり、以下のディレクトリとファイルが適切に配置されている必要があります。スクリプトは一部のディレクトリを自動的に作成しますが、主要な入力元となるディレクトリは事前に準備しておく必要があります。

1. 入力元となる必須ディレクトリ

  • ${HOME}/Downloads (DOWNLOADS_DIR):

    • 目的: Minecraftサーバーの稼働に必要なJARファイル群を格納するディレクトリです。
    • 内容:
      • PaperMCサーバーJARファイル: paper-*.jar の形式で、最新のPaperMCサーバーJARファイルがここに存在する必要があります。スクリプトはこのディレクトリから最新のPaperMCサーバーJARファイルを自動的に検出します。
      • プラグインJARファイル: 新しいサーバーの plugins フォルダにコピーしたいMinecraftプラグインのJARファイルもここに配置します。スクリプトは、PaperMCサーバーJAR以外の全てのJARファイルを自動的に plugins フォルダにコピーします。
    • 重要性: このディレクトリ内にPaperMCサーバーJARファイルが存在しない場合、スクリプトはサーバーのセットアップを続行できません。
  • ${HOME}/.minecraft_backups (MINECRAFT_BACKUPS_DIR):

    • 目的: MinecraftワールドのバックアップZIPファイルを格納するディレクトリです。
    • 内容: minecraft-server_YYYYMMDDHHMMSS.zip の形式で、過去に作成されたMinecraftワールドのバックアップZIPファイルが格納されます。
    • 重要性: 「バックアップからの復元」モードを使用する場合、このディレクトリ内に復元対象のZIPファイルが存在する必要があります。 スクリプトは、このディレクトリが存在しない場合、自動的に作成します。

2. スクリプトが自動的に作成・利用するディレクトリ

  • ${HOME}/.minecraft_worlds (MINECRAFT_WORLDS_DIR):

    • 目的: スクリプトによって作成されますが、現在のスクリプトのロジックでは、アクティブなワールドデータやバックアップの直接的な保存には使用されていません。将来的な拡張や、特定の運用慣習のために予約されている可能性があります。
    • 重要性: スクリプトの実行には必須ではありませんが、スクリプトが自動的に作成します。
  • ${HOME}/.bak (CLEANUP_BAK_DIR):

    • 目的: 古いMinecraftサーバーディレクトリを一時的に移動させるためのクリーンアップディレクトリです。
    • 内容: mc_backup.sh の実行によって新しくサーバーがセットアップされた後、以前のサーバーディレクトリ(例: .minecraft_server_YYYYMMDDHHMMSS)がここに移動されます。
    • 重要性: スクリプトのクリーンアップ機能に必須です。このディレクトリが存在しない場合、スクリプトが自動的に作成します。
  • ${HOME}/.minecraft_server_YYYYMMDDHHMMSS (NEW_SERVER_DIR):

    • 目的: mc_backup.sh の実行によって新しくセットアップされるMinecraftサーバーのルートディレクトリです。ディレクトリ名には実行時のタイムスタンプが付与され、一意性が保証されます。
    • 内容: server.jareula.txtserver.propertiesplugins/ ディレクトリ、そしてMinecraftワールドデータ(worldworld_netherworld_the_end)など、サーバー稼働に必要な全てのファイルとディレクトリが格納されます。
    • 重要性: スクリプトの主要な出力先であり、新しいサーバー環境の基盤となります。
  • ${HOME}/start_minecraft.sh:

    • 目的: mc_backup.sh によって自動的に生成または更新される補助スクリプトです。このスクリプトを実行することで、mc_backup.sh によって作成された最新のMinecraftサーバーインスタンスを簡単に起動できます。
    • 内容: $HOME ディレクトリ直下にある最新の minecraft_server_* または .minecraft_server_* 形式のディレクトリを自動的に特定し、その中の server.jar を実行するシンプルなシェルスクリプトです。
    • 重要性: 新しくセットアップされたサーバーを迅速に起動するために不可欠です。

スクリプトの実行方法

mc_backup.sh は、以下のコマンドで実行できます。

bash ${HOME}/gemini_workspace/mc_backup.sh

実行後、スクリプトは対話形式で、既存ワールドの更新か、バックアップからの復元かを選択するよう促します。

mc_backup.sh スクリプト本体

#!/bin/bash
#
# スクリプト名: mc_backup.sh
# 概要: Minecraft Paperサーバーのバックアップと復元、または既存ワールドデータからの新規セットアップを行うスクリプト。
#       - 既存の稼働中ワールドデータが存在する場合: そのデータを使用して新しいサーバーをセットアップします(最優先)。
#       - 既存の稼働中ワールドデータがなく、バックアップZIPが存在する場合: 一覧から選択してワールドを復元します。
#       - どちらも存在しない場合: スクリプトを終了します。
#
# 前提条件:
#   - 最新の PaperMC サーバーJARファイル (例: paper-*.jar) が
#     '${DOWNLOADS_DIR}' ディレクトリに存在すること。
#   - プラグインとしてコピーしたいJARファイルも '${DOWNLOADS_DIR}' に配置すること。
#   - 復元したいワールドデータのZIPファイルが '${MINECRAFT_BACKUPS_DIR}' に存在する場合、
#     その中から選択します。
#
# ダウンロード元:
#   - https://papermc.io/downloads/paper
#   - https://ci.viaversion.com/job/ViaVersion/
#   - https://ci.viaversion.com/view/ViaBackwards/job/ViaBackwards/
#   - https://geysermc.org/download?project=geyser
#   - https://geysermc.org/download/?project=floodgate
#
# 実行結果:
#   - 新しいサーバーディレクトリが '${HOME}/.minecraft_server_...' に作成されます。
#
# 注意事項:
#   - 初回起動時にEULAに同意するため、一時的にサーバーが起動・停止します。
#   - server.properties の設定は、このスクリプトによって上書きされます。
#
# デバッグモード: true にすると詳細なデバッグメッセージが表示されます
DEBUG_MODE=false

DOWNLOADS_DIR="${HOME}/Downloads"
NEW_SERVER_ROOT="${HOME}"

MINECRAFT_BACKUPS_DIR="${HOME}/.minecraft_backups"
MINECRAFT_WORLDS_DIR="${HOME}/.minecraft_worlds"
CLEANUP_BAK_DIR="${HOME}/.bak" # 古いサーバーを移動するディレクトリ

TIMESTAMP=$(date +%Y%m%d%H%M%S)
NEW_SERVER_DIR="${NEW_SERVER_ROOT}/.minecraft_server_${TIMESTAMP}" # 新しいサーバーディレクトリは隠しディレクトリに

mkdir -p "${MINECRAFT_BACKUPS_DIR}"
mkdir -p "${MINECRAFT_WORLDS_DIR}"
mkdir -p "${CLEANUP_BAK_DIR}"

# server.properties の設定を更新または追記する関数
# 引数: $1 = 設定ファイルパス, $2 = 設定キー, $3 = 設定値
set_server_property() {
    local file="$1"
    local key="$2"
    local value="$3"

    if grep -q "^${key}=" "$file"; then
        # 既存の設定を更新
        sed -i "s/^${key}=.*/${key}=${value}/g" "$file"
        echo "  - ${key} を '${value}' に設定しました。"
    else
        # 設定が存在しない場合は追記
        echo "${key}=${value}" >> "$file"
        echo "  - ${key} を '${value}' として追記しました。"
    fi
}

# --- 初期チェックとモード決定 ---
echo "初期チェックを行っています..."

# 既存の稼働中サーバーディレクトリを特定
LATEST_EXISTING_SERVER_DIR=$(find "${NEW_SERVER_ROOT}" -maxdepth 1 -type d \( -name "minecraft_server_*" -o -name ".minecraft_server_*" \) | sort -r | head -n 1)
HAS_EXISTING_WORLD=false
if [ -n "$LATEST_EXISTING_SERVER_DIR" ] && [ -d "${LATEST_EXISTING_SERVER_DIR}/world" ]; then
    HAS_EXISTING_WORLD=true
fi

# バックアップZIPファイルのリストを取得
WORLD_ZIP_FILES=()
while IFS= read -r -d '' REPLY; do
    WORLD_ZIP_FILES+=("$REPLY")
done < <(find "${MINECRAFT_BACKUPS_DIR}" -maxdepth 1 -name "minecraft-server_*.zip" -print0 | sort -z -r)

SELECTED_ZIP=""
MODE="NONE" # "RESTORE_FROM_ZIP", "UPDATE_EXISTING", "EXIT"

# どちらの操作もできない場合は終了
if [ "$HAS_EXISTING_WORLD" = false ] && [ ${#WORLD_ZIP_FILES[@]} -eq 0 ]; then
    echo "エラー: 復元可能なバックアップZIPファイルも、更新可能な既存のワールドデータも見つかりませんでした。スクリプトを終了します。"
    exit 1
fi

echo ""
echo "--- 実行モードの選択 ---"
echo "以下のいずれかの操作を選択してください:"
if [ "$HAS_EXISTING_WORLD" = true ]; then
    echo "  1) 既存の稼働中ワールドデータを使用して新しいサーバーを構築(更新)する"
fi
if [ ${#WORLD_ZIP_FILES[@]} -gt 0 ]; then
    echo "  2) バックアップZIPファイルからワールドを復元する"
fi
echo "  0) スクリプトを終了する"
echo "------------------------"

while true; do
    read -p "選択肢の番号を入力してください: " MAIN_CHOICE
    if [[ "$MAIN_CHOICE" =~ ^[0-9]+$ ]]; then
        if [ "$MAIN_CHOICE" -eq 0 ]; then
            echo "ユーザーによってキャンセルされました。スクリプトを終了します。"
            exit 0
        elif [ "$MAIN_CHOICE" -eq 1 ] && [ "$HAS_EXISTING_WORLD" = true ]; then
            MODE="UPDATE_EXISTING"
            echo "既存の稼働中ワールドデータを使用して新しいサーバーを構築(更新)します。"
            break
        elif [ "$MAIN_CHOICE" -eq 2 ] && [ ${#WORLD_ZIP_FILES[@]} -gt 0 ]; then
            MODE="RESTORE_FROM_ZIP"
            echo "バックアップZIPファイルからワールドを復元します。"
            # ここでZIP選択ロジックを呼び出す
            echo ""
            echo "--- ワールドバックアップZIPの選択 ---"
            echo "以下のバックアップZIPファイルが見つかりました:"
            for i in "${!WORLD_ZIP_FILES[@]}"; do
                echo "  $((i+1))) $(basename "${WORLD_ZIP_FILES[$i]}")"
            done
            echo "-----------------------------------"

            while true; do
                read -p "使用するバックアップZIPの番号を入力してください: " CHOICE
                if [[ "$CHOICE" =~ ^[0-9]+$ ]]; then
                    if [ "$CHOICE" -ge 1 ] && [ "$CHOICE" -le ${#WORLD_ZIP_FILES[@]} ]; then
                        SELECTED_ZIP="${WORLD_ZIP_FILES[$((CHOICE-1))]}"
                        echo "  - 選択されたワールドバックアップZIP: $(basename "$SELECTED_ZIP")"
                        break
                    else
                        echo "無効な入力です。1から${#WORLD_ZIP_FILES[@]}までの数字を入力してください。"
                    fi
                else
                    echo "無効な入力です。数字を入力してください。"
                fi
            done
            break # Break from main_choice loop
        else
            echo "無効な入力です。利用可能な選択肢から選んでください。"
        fi
    else
        echo "無効な入力です。数字を入力してください。"
    fi
done

echo "すべての必要なファイルが確認されました。セットアップを続行します。モード: $MODE"
# --- 初期チェックとモード決定終了 ---

# --- 既存ワールドデータの自動バックアップ (UPDATE_EXISTING モードの場合、またはRESTORE_FROM_ZIPだが既存ワールドがある場合) ---
if [ "$HAS_EXISTING_WORLD" = true ]; then # 既存ワールドがある場合は常にバックアップ
    echo "既存のワールドデータがあれば、自動でバックアップします..."
    # LATEST_EXISTING_SERVER_DIR は既に特定済み
    if [ -n "$LATEST_EXISTING_SERVER_DIR" ] && [ -d "${LATEST_EXISTING_SERVER_DIR}/world" ]; then
        # シンボリックリンクではなく、実際のディレクトリをバックアップ
        WORLD_REAL_PATH="${LATEST_EXISTING_SERVER_DIR}/world"
        NETHER_REAL_PATH="${LATEST_EXISTING_SERVER_DIR}/world_nether"
        THE_END_REAL_PATH="${LATEST_EXISTING_SERVER_DIR}/world_the_end"

        if [ -d "$WORLD_REAL_PATH" ]; then
            BACKUP_TIMESTAMP=$(date +%Y%m%d%H%M%S)
            BACKUP_ZIP_PATH="${MINECRAFT_BACKUPS_DIR}/minecraft-server_${BACKUP_TIMESTAMP}.zip"
            echo "  - 既存のワールドデータ '${WORLD_REAL_PATH}' を '${BACKUP_ZIP_PATH}' にバックアップ中..."
            zip -r "$BACKUP_ZIP_PATH" "$WORLD_REAL_PATH" "$NETHER_REAL_PATH" "$THE_END_REAL_PATH" > /dev/null
            if [ $? -ne 0 ]; then
                echo "警告: 既存ワールドデータのバックアップに失敗しました。手動で確認してください。"
            else
                echo "  - 既存ワールドデータのバックアップが完了しました。"
            fi
        else
            echo "  - 最新のサーバーディレクトリにワールドデータの実体が見つかりませんでした。スキップします。"
        fi
    else
        echo "  - 既存のサーバーディレクトリまたはワールドデータが見つかりませんでした。スキップします。"
    fi
fi
# --- 自動バックアップ終了 ---


# 1. 新しいサーバーディレクトリの作成
# 指定されたパスに新しいサーバーディレクトリを作成します。
# 既に存在する場合は何もしません。作成に失敗した場合はエラーを出力しスクリプトを終了します。
mkdir -p "${NEW_SERVER_DIR}"
if [ $? -ne 0 ]; then
  echo "エラー: サーバーディレクトリの作成に失敗しました。スクリプトを終了します。"
  exit 1
fi
echo "サーバーディレクトリ '${NEW_SERVER_DIR}' を作成しました。"

# 2. サーバーJARのコピー
# 検出したサーバーJARファイルを新しいサーバーディレクトリに「server.jar」としてコピーします。
# コピーに失敗した場合はエラーを出力しスクリプトを終了します。
SERVER_JAR=$(find "${DOWNLOADS_DIR}" -maxdepth 1 -name "paper-*.jar" | sort -r | head -n 1)
if [ -z "$SERVER_JAR" ]; then
  echo "エラー: ダウンロードディレクトリに Paper サーバーJARファイルが見つかりませんでした。スクリプトを終了します。"
  exit 1
fi
echo "最新のサーバーJARファイル: $(basename "$SERVER_JAR") を使用します。"

cp "$SERVER_JAR" "${NEW_SERVER_DIR}/server.jar"
if [ $? -ne 0 ]; then
  echo "エラー: サーバーJARファイルのコピーに失敗しました。スクリプトを終了します。"
  exit 1
fi
echo "サーバーJARファイルをコピーしました。"

# 3. 初回起動(EULAと初期ファイル生成)
# EULA (End User License Agreement) と server.properties などの初期ファイルを生成するために、
# サーバーを一時的に起動します。--noguiオプションでGUIなしで起動し、バックグラウンドで実行します。
echo "初回起動を実行し、初期ファイルを生成します..."
(cd "${NEW_SERVER_DIR}" && java -jar server.jar --nogui) &
SERVER_PID=$!

# eula.txt と server.properties が生成されるまで待機
# サーバーが初期ファイルを生成するまで最大60秒間待機します。
# タイムアウトした場合は警告を表示し、手動での確認を促します。
EULA_FILE="${NEW_SERVER_DIR}/eula.txt"
PROPERTIES_FILE="${NEW_SERVER_DIR}/server.properties"
TIMEOUT=60 # タイムアウトを60秒に設定

echo "eula.txt と server.properties の生成を待機中..."
for i in $(seq 1 $TIMEOUT); do
  if [ -f "$EULA_FILE" ] && [ -f "$PROPERTIES_FILE" ]; then
    echo "eula.txt と server.properties が生成されました。"
    break
  fi
  sleep 1
  if [ $i -eq $TIMEOUT ]; then
    echo "警告: eula.txt または server.properties の生成がタイムアウトしました。手動で確認してください。"
  fi
done

# 初回起動したサーバープロセスを終了します。
kill ${SERVER_PID} # サーバープロセスを終了
wait ${SERVER_PID} 2>/dev/null # プロセスが完全に終了するのを待つ
echo "初回起動が完了し、初期ファイルが生成されました。"

# 4. EULAの同意
# 生成された eula.txt ファイルの 'eula=false' を 'eula=true' に変更し、EULAに同意します。
# ファイルが見つからない場合は警告を表示します。
if [ -f "$EULA_FILE" ]; then
  sed -i 's/eula=false/eula=true/g' "$EULA_FILE"
  echo "eula.txt を true に設定しました。"
else
  echo "警告: eula.txt が見つかりませんでした。手動で設定してください。"
fi

# 5. プラグインのコピー (サーバーJAR以外の全てのJARファイルをコピー)
# ダウンロードディレクトリにあるサーバーJAR以外の全てのJARファイルを、
# 新しいサーバーディレクトリ内の 'plugins' フォルダにコピーします。
PLUGINS_DIR="${NEW_SERVER_DIR}/plugins"
mkdir -p "${PLUGINS_DIR}"
echo "プラグインのコピーを開始します..."

if "$DEBUG_MODE"; then
    echo "デバッグ: ダウンロードディレクトリ (${DOWNLOADS_DIR}) の内容:"
    ls -l "${DOWNLOADS_DIR}"
fi

find "${DOWNLOADS_DIR}" -maxdepth 1 -name "*.jar" -print0 | while IFS= read -r -d '' JAR_FILE; do
  if "$DEBUG_MODE"; then
      echo "デバッグ: find が検出したJARファイル: $(basename "$JAR_FILE")"
  fi
  if [ "$(basename "$JAR_FILE")" != "$(basename "$SERVER_JAR")" ]; then
    echo "  - $(basename "$JAR_FILE") をプラグインとしてコピーします。"
    cp "$JAR_FILE" "${PLUGINS_DIR}/"
  fi
done
echo "プラグインのコピーが完了しました。"

echo "プラグインフォルダの内容:"
ls -l "${PLUGINS_DIR}"


# 6. server.properties のカスタマイズ
# server.properties ファイルをユーザーの入力と自動設定に基づいてカスタマイズします。
# 各設定項目は、存在すれば更新し、存在しなければ追記します。
if [ -f "$PROPERTIES_FILE" ]; then
  echo "server.properties をカスタマイズしています..."
  set_server_property "$PROPERTIES_FILE" "enforce-secure-profile" "false"
  # 必要に応じて他の server.properties 設定もここに追加
else
  echo "警告: server.properties が見つかりませんでした。設定は手動で確認してください。"
fi

# 7. ワールドデータの展開と直接配置
if [ "$MODE" = "RESTORE_FROM_ZIP" ]; then
    echo "選択されたワールドZIPファイル '$(basename "$SELECTED_ZIP")' を展開します..."
    # ワールドデータの実体を新しいサーバーディレクトリに直接展開
    TEMP_WORLD_DIR=$(mktemp -d) # 一時ディレクトリを作成
    unzip -q "$SELECTED_ZIP" -d "$TEMP_WORLD_DIR" # -q でログを抑制

    # ZIP内のパスからworld, world_nether, world_the_end ディレクトリを探す
    WORLD_PATH_IN_ZIP=$(find "$TEMP_WORLD_DIR" -type d -name "world" | head -n 1)
    NETHER_PATH_IN_ZIP=$(find "$TEMP_WORLD_DIR" -type d -name "world_nether" | head -n 1)
    THE_END_PATH_IN_ZIP=$(find "$TEMP_WORLD_DIR" -type d -name "world_the_end" | head -n 1)

    if [ -n "$WORLD_PATH_IN_ZIP" ] && [ -n "$NETHER_PATH_IN_ZIP" ] && [ -n "$THE_END_PATH_IN_ZIP" ]; then
        # 既存のワールドディレクトリを削除(初回起動で生成されたもの)
        rm -rf "${NEW_SERVER_DIR}/world" "${NEW_SERVER_DIR}/world_nether" "${NEW_SERVER_DIR}/world_the_end"
        
        mv "$WORLD_PATH_IN_ZIP" "${NEW_SERVER_DIR}/"
        mv "$NETHER_PATH_IN_ZIP" "${NEW_SERVER_DIR}/"
        mv "$THE_END_PATH_IN_ZIP" "${NEW_SERVER_DIR}/"
        echo "ワールドデータを '${NEW_SERVER_DIR}' に展開しました。"
    else
        echo "エラー: ワールドデータがZIPファイル内で想定されるパスに見つかりませんでした。手動で確認してください。"
        rm -rf "$TEMP_WORLD_DIR" # 一時ディレクトリを削除
        exit 1
    fi

    rm -rf "$TEMP_WORLD_DIR" # 一時ディレクトリを削除
    echo "一時ディレクトリを削除しました。"

elif [ "$MODE" = "UPDATE_EXISTING" ]; then
    echo "既存の稼働中ワールドデータを使用して新しいサーバーを構築します。"
    # 既存のワールドデータを新しいサーバーディレクトリに直接コピー
    if [ -n "$LATEST_EXISTING_SERVER_DIR" ] && [ -d "${LATEST_EXISTING_SERVER_DIR}/world" ]; then
        echo "既存のワールドデータ '${LATEST_EXISTING_SERVER_DIR}/world' を使用します。"
        # 既存のワールドディレクトリを削除(初回起動で生成されたもの)
        rm -rf "${NEW_SERVER_DIR}/world" "${NEW_SERVER_DIR}/world_nether" "${NEW_SERVER_DIR}/world_the_end"

        cp -r "${LATEST_EXISTING_SERVER_DIR}/world" "${NEW_SERVER_DIR}/"
        cp -r "${LATEST_EXISTING_SERVER_DIR}/world_nether" "${NEW_SERVER_DIR}/"
        cp -r "${LATEST_EXISTING_SERVER_DIR}/world_the_end" "${NEW_SERVER_DIR}/"
        echo "既存ワールドデータを新しいサーバーディレクトリにコピーしました。"
    else
        echo "エラー: 既存の稼働中ワールドデータが見つかりませんでした。スクリプトを終了します。"
        exit 1 # This should ideally be caught by initial checks, but good to have
    fi
else
    # This case should ideally not be reached if initial checks are robust
    echo "エラー: 不明なモードです。スクリプトを終了します。"
    exit 1
fi


echo "✨ Minecraftサーバーのセットアップとワールド復元が完了しました! ✨"
echo ""
echo "新しいサーバーは以下の場所に作成されました:"
echo "  -> ${NEW_SERVER_DIR}"
echo ""

# --- start_minecraft.sh の更新 ---
# start_minecraft.sh スクリプトを更新し、常に最新のサーバーディレクトリを起動するようにします。
# このロジックは、ディレクトリ名にタイムスタンプが含まれることを前提としています。
START_MINECRAFT_SCRIPT="${HOME}/start_minecraft.sh"

cat << EOF > "$START_MINECRAFT_SCRIPT"
#!/bin/bash

# 最新のMinecraftサーバーディレクトリを特定 (隠しディレクトリも含む)
LATEST_SERVER_DIR=\$(find "${NEW_SERVER_ROOT}" -maxdepth 1 -type d -name "minecraft_server_*" -o -name ".minecraft_server_*" | sort -r | head -n 1)

if [ -z "\$LATEST_SERVER_DIR" ]; then
  echo "エラー: 最新のMinecraftサーバーディレクトリが見つかりませんでした。"
  exit 1
fi

echo "最新のMinecraftサーバー: \$(basename "\$LATEST_SERVER_DIR") を起動します..."

# サーバーディレクトリに移動して起動
cd "\$LATEST_SERVER_DIR" && java -jar server.jar --nogui
EOF

chmod +x "$START_MINECRAFT_SCRIPT"
echo "'${START_MINECRAFT_SCRIPT}' を更新しました。"

# --- 古いサーバーディレクトリの整理 ---
# 最新のサーバーディレクトリ以外の古いサーバーディレクトリを、指定されたクリーンアップディレクトリに移動します。
echo "古いサーバーディレクトリを整理します..."
mkdir -p "${CLEANUP_BAK_DIR}" # .bak ディレクトリが存在しない場合は作成

# 最新のサーバーディレクトリ以外のサーバーディレクトリを特定し、.bak に移動
find "${NEW_SERVER_ROOT}" -maxdepth 1 -type d \( -name "minecraft_server_*" -o -name ".minecraft_server_*" \) -not -name "$(basename "$NEW_SERVER_DIR")" | while read -r OLD_SERVER_DIR; do
  echo "  - 古いサーバー '${OLD_SERVER_DIR}' を '${CLEANUP_BAK_DIR}/' に移動します。"
  mv "$OLD_SERVER_DIR" "${CLEANUP_BAK_DIR}/"
done
echo "古いサーバーディレクトリの整理が完了しました。"

echo "サーバーを起動するには、以下のスクリプトを実行してください:"
echo "  -> ${HOME}/start_minecraft.sh"
echo ""
echo "例: bash ${HOME}/start_minecraft.sh"

Minecraft Paperサーバー管理スクリプト: mc_backup.sh の実行動画

まとめ

本稿では、Minecraft Paperサーバーの管理を効率化するシェルスクリプトmc_backup.shの詳細な機能と、その運用に必要なディレクトリ構造について解説しました。このスクリプトは、サーバーの新規セットアップ、既存ワールドの更新、バックアップからの復元、そして自動的なクリーンアップと起動スクリプトの更新を統合的に行うことで、Minecraftサーバー管理の複雑さを大幅に軽減します。

適切なディレクトリ構成と、mc_backup.shの提供するモード選択を活用することで、ユーザーは自身のMinecraftサーバー環境を柔軟かつ安全に管理することが可能になります。本記事が、Minecraftサーバー運用の一助となれば幸いです。

本記事に記載されている情報は、特定の環境下での成功事例に基づいています。お使いの環境や設定によっては、記載通りの動作を保証するものではありません。導入の際は、ご自身の責任において実施してください。

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?