本記事は 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
は、以下の主要な機能を提供します。
-
既存ワールドデータからの新規セットアップ(更新モード):
- 既に稼働中のMinecraftサーバーのワールドデータが存在する場合、そのデータを使用して新しいサーバー環境を構築します。これにより、既存の進捗を維持したまま、新しいサーバーバージョンやプラグイン環境への移行が容易になります。
-
バックアップからのワールド復元(復元モード):
- 既存のワールドデータが見つからない場合、事前に作成されたバックアップZIPファイルの一覧から選択し、指定されたワールドデータを復元します。これにより、予期せぬデータ損失からの回復や、過去の特定時点のワールドへのロールバックが可能になります。
-
自動バックアップとクリーンアップ:
- 既存ワールドデータを使用して更新モードを実行する際、現在のワールドデータを自動的にバックアップします。
- 新しいサーバー環境のセットアップ後、古いサーバーディレクトリを自動的に指定されたクリーンアップディレクトリへ移動し、ディスクスペースの整理を支援します。
-
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ファイル:
- 重要性: このディレクトリ内に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.jar
、eula.txt
、server.properties
、plugins/
ディレクトリ、そしてMinecraftワールドデータ(world
、world_nether
、world_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サーバー運用の一助となれば幸いです。
本記事に記載されている情報は、特定の環境下での成功事例に基づいています。お使いの環境や設定によっては、記載通りの動作を保証するものではありません。導入の際は、ご自身の責任において実施してください。