tools: scope mcc debug runtime artifacts by session

This commit is contained in:
BruceChen 2026-04-12 19:38:53 +08:00
parent afee31e918
commit bf292ea1be
3 changed files with 129 additions and 28 deletions

View file

@ -16,6 +16,8 @@ Options:
-v, --version VER Server directory name (default: 1.21.11-Vanilla) -v, --version VER Server directory name (default: 1.21.11-Vanilla)
-m, --mode MODE Console mode: classic or tui (default: classic) -m, --mode MODE Console mode: classic or tui (default: classic)
-p, --port PORT Server port (default: 25565) -p, --port PORT Server port (default: 25565)
--session NAME Session name for scoped runtime artifacts
--username NAME MCC username (default: resolved from session)
--no-build Skip dotnet build --no-build Skip dotnet build
--debug-on Enable debug messages from the start --debug-on Enable debug messages from the start
--file-input Use FileInput mode (classic only; enables mcc-cmd) --file-input Use FileInput mode (classic only; enables mcc-cmd)
@ -25,6 +27,7 @@ Examples:
tools/mcc-debug.sh # Classic mode, default server tools/mcc-debug.sh # Classic mode, default server
tools/mcc-debug.sh -m tui # TUI mode tools/mcc-debug.sh -m tui # TUI mode
tools/mcc-debug.sh -v 1.21.11-Vanilla --debug-on tools/mcc-debug.sh -v 1.21.11-Vanilla --debug-on
tools/mcc-debug.sh --session smoke-a --username SmokeA
tools/mcc-debug.sh --file-input # FileInput for script-driven testing tools/mcc-debug.sh --file-input # FileInput for script-driven testing
EOF EOF
} }
@ -33,6 +36,8 @@ VERSION="1.21.11-Vanilla"
MODE="classic" MODE="classic"
PORT="25565" PORT="25565"
PORT_SET_BY_USER=false PORT_SET_BY_USER=false
SESSION=""
USERNAME=""
DO_BUILD=true DO_BUILD=true
DEBUG_ON=false DEBUG_ON=false
FILE_INPUT=false FILE_INPUT=false
@ -42,6 +47,8 @@ while [[ $# -gt 0 ]]; do
-v|--version) VERSION="$2"; shift 2 ;; -v|--version) VERSION="$2"; shift 2 ;;
-m|--mode) MODE="$2"; shift 2 ;; -m|--mode) MODE="$2"; shift 2 ;;
-p|--port) PORT="$2"; PORT_SET_BY_USER=true; shift 2 ;; -p|--port) PORT="$2"; PORT_SET_BY_USER=true; shift 2 ;;
--session) SESSION="$2"; shift 2 ;;
--username) USERNAME="$2"; shift 2 ;;
--no-build) DO_BUILD=false; shift ;; --no-build) DO_BUILD=false; shift ;;
--debug-on) DEBUG_ON=true; shift ;; --debug-on) DEBUG_ON=true; shift ;;
--file-input) FILE_INPUT=true; shift ;; --file-input) FILE_INPUT=true; shift ;;
@ -50,23 +57,38 @@ while [[ $# -gt 0 ]]; do
esac esac
done done
TEST_ROOT="${TMPDIR:-/tmp}/mcc-debug" SESSION="$(_mcc_resolve_session "$SESSION")"
CFG="$TEST_ROOT/MinecraftClient.debug.ini" if [[ -z "$USERNAME" ]]; then
MCC_LOG="$TEST_ROOT/mcc-debug.log" USERNAME="$(_mcc_resolve_username "$SESSION")"
INPUT_FILE="$REPO_ROOT/mcc_input.txt" fi
SESSION_ROOT="$(_mcc_session_root "$SESSION")"
CFG="$SESSION_ROOT/MinecraftClient.debug.ini"
MCC_LOG="$(_mcc_session_log_file "$SESSION")"
INPUT_FILE="$(_mcc_session_input_file "$SESSION")"
PID_FILE="$(_mcc_session_pid_file "$SESSION")"
META_FILE="$(_mcc_session_meta_file "$SESSION")"
MCC_TMUX_SESSION="$(_mcc_tmux_session_name "$SESSION")"
SESSION_NAME="mc-${VERSION//\./_}" SESSION_NAME="mc-${VERSION//\./_}"
PREPARE_CFG_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh" PREPARE_CFG_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh"
ENSURE_SERVER_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/ensure_offline_server.sh" ENSURE_SERVER_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/ensure_offline_server.sh"
PREFLIGHT_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/preflight_test_env.sh" PREFLIGHT_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/preflight_test_env.sh"
GET_PORT_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/get_server_port.sh" GET_PORT_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/get_server_port.sh"
mkdir -p "$TEST_ROOT" mkdir -p "$SESSION_ROOT"
echo "=== MCC Debug Session ===" echo "=== MCC Debug Session ==="
echo " Server: $VERSION (port $PORT)" echo " Server: $VERSION (port $PORT)"
echo " Session: $SESSION"
echo " User: $USERNAME"
echo " Mode: $MODE" echo " Mode: $MODE"
echo " Root: $SESSION_ROOT"
echo " Config: $CFG" echo " Config: $CFG"
echo " Log: $MCC_LOG" echo " Log: $MCC_LOG"
echo " Input: $INPUT_FILE"
echo " PID: $PID_FILE"
echo " Meta: $META_FILE"
echo " Tmux: $MCC_TMUX_SESSION"
echo "" echo ""
bash "$PREFLIGHT_SCRIPT" "$VERSION" >/dev/null bash "$PREFLIGHT_SCRIPT" "$VERSION" >/dev/null
@ -82,7 +104,7 @@ fi
# --- Prepare config --- # --- Prepare config ---
echo "[2/4] Preparing config..." echo "[2/4] Preparing config..."
bash "$PREPARE_CFG_SCRIPT" "$CFG" "${VERSION%-Vanilla}" CursorBot >/dev/null bash "$PREPARE_CFG_SCRIPT" "$CFG" "${VERSION%-Vanilla}" "$USERNAME" >/dev/null
if [[ "$MODE" == "tui" ]]; then if [[ "$MODE" == "tui" ]]; then
if [[ "$(uname)" == "Darwin" ]]; then if [[ "$(uname)" == "Darwin" ]]; then
@ -130,34 +152,55 @@ if ! $PORT_SET_BY_USER; then
PORT="$(bash "$GET_PORT_SCRIPT" "$VERSION")" PORT="$(bash "$GET_PORT_SCRIPT" "$VERSION")"
fi fi
RUNTIME_MODE="$MODE"
if $FILE_INPUT; then
RUNTIME_MODE="${MODE}-file-input"
fi
cat > "$META_FILE" <<EOF
session=$SESSION
user=$USERNAME
mode=$RUNTIME_MODE
config=$CFG
log=$MCC_LOG
input=$INPUT_FILE
pid=$PID_FILE
tmux=$MCC_TMUX_SESSION
server_version=$VERSION
server_port=$PORT
EOF
# --- Launch MCC --- # --- Launch MCC ---
echo "[4/4] Launching MCC in $MODE mode..." echo "[4/4] Launching MCC in $MODE mode..."
: > "$INPUT_FILE" : > "$INPUT_FILE"
rm -f "$MCC_LOG" rm -f "$MCC_LOG"
rm -f "$PID_FILE"
MCC_ARGS=("$CFG" "CursorBot" "-" "localhost:$PORT") MCC_ARGS=("$CFG" "$USERNAME" "-" "localhost:$PORT")
if [[ "$MODE" == "tui" ]]; then if [[ "$MODE" == "tui" ]]; then
# TUI mode: needs a real tty — no pipes or redirects allowed # TUI mode: needs a real tty - no pipes or redirects allowed
tmux kill-session -t mcc-debug 2>/dev/null || true tmux kill-session -t "$MCC_TMUX_SESSION" 2>/dev/null || true
tmux new-session -d -s mcc-debug -x 160 -y 50 \ tmux new-session -d -s "$MCC_TMUX_SESSION" -x 160 -y 50 \
"cd '$REPO_ROOT' && dotnet run --project MinecraftClient -c Release --no-build -- ${MCC_ARGS[*]}; echo '=== MCC EXITED ==='; sleep 600" "cd '$REPO_ROOT' && dotnet run --project MinecraftClient -c Release --no-build -- ${MCC_ARGS[*]}; echo '=== MCC EXITED ==='; sleep 600"
echo "" echo ""
echo " TUI mode started in tmux session 'mcc-debug'" echo " TUI mode started in tmux session '$MCC_TMUX_SESSION'"
echo " (TUI mode uses a real terminal; log file is not available, use MCC's /debug command)" echo " (TUI mode uses a real terminal; log file is not available, use MCC's /debug command)"
echo "" echo ""
echo " Attach: tmux attach -t mcc-debug" echo " Attach: tmux attach -t $MCC_TMUX_SESSION"
echo " Detach: Ctrl+B, D" echo " Detach: Ctrl+B, D"
echo " Kill MCC: tmux kill-session -t mcc-debug" echo " Kill MCC: tmux kill-session -t $MCC_TMUX_SESSION"
echo "" echo ""
elif $FILE_INPUT; then elif $FILE_INPUT; then
# FileInput mode: run in background, drive via mcc_input.txt # FileInput mode: run in background, drive via session-specific input file
( (
cd "$REPO_ROOT" cd "$REPO_ROOT"
MCC_FILE_INPUT=1 dotnet run --project MinecraftClient -c Release --no-build -- "${MCC_ARGS[@]}" > "$MCC_LOG" 2>&1 MCC_FILE_INPUT=1 MCC_INPUT_FILE="$INPUT_FILE" dotnet run --project MinecraftClient -c Release --no-build -- "${MCC_ARGS[@]}" > "$MCC_LOG" 2>&1
) & ) &
MCC_PID=$! MCC_PID=$!
printf '%s\n' "$MCC_PID" > "$PID_FILE"
echo " MCC PID: $MCC_PID" echo " MCC PID: $MCC_PID"
echo " MCC PID file: $PID_FILE"
echo "" echo ""
sleep 5 sleep 5
@ -175,25 +218,26 @@ elif $FILE_INPUT; then
echo "" echo ""
echo " Send commands: echo 'debug state' >> $INPUT_FILE" echo " Send commands: echo 'debug state' >> $INPUT_FILE"
echo " Tail log: tail -f $MCC_LOG" echo " Tail log: tail -f $MCC_LOG"
echo " Metadata: cat $META_FILE"
echo " Stop MCC: echo 'quit' >> $INPUT_FILE" echo " Stop MCC: echo 'quit' >> $INPUT_FILE"
echo " Stop server: mc-stop $VERSION" echo " Stop server: mc-stop $VERSION"
echo "" echo ""
else else
# Interactive classic mode: run in tmux (no pipe ConsoleInteractive also needs tty) # Interactive classic mode: run in tmux (no pipe - ConsoleInteractive also needs tty)
tmux kill-session -t mcc-debug 2>/dev/null || true tmux kill-session -t "$MCC_TMUX_SESSION" 2>/dev/null || true
tmux new-session -d -s mcc-debug -x 160 -y 50 \ tmux new-session -d -s "$MCC_TMUX_SESSION" -x 160 -y 50 \
"cd '$REPO_ROOT' && dotnet run --project MinecraftClient -c Release --no-build -- ${MCC_ARGS[*]}; echo '=== MCC EXITED ==='; sleep 600" "cd '$REPO_ROOT' && dotnet run --project MinecraftClient -c Release --no-build -- ${MCC_ARGS[*]}; echo '=== MCC EXITED ==='; sleep 600"
echo "" echo ""
echo " Classic mode started in tmux session 'mcc-debug'" echo " Classic mode started in tmux session '$MCC_TMUX_SESSION'"
echo "" echo ""
echo " Attach: tmux attach -t mcc-debug" echo " Attach: tmux attach -t $MCC_TMUX_SESSION"
echo " Detach: Ctrl+B, D" echo " Detach: Ctrl+B, D"
echo " Kill MCC: tmux kill-session -t mcc-debug" echo " Kill MCC: tmux kill-session -t $MCC_TMUX_SESSION"
echo " Note: Use MCC's built-in /debug command or enable LogToFile for log output" echo " Note: Use MCC's built-in /debug command or enable LogToFile for log output"
echo "" echo ""
fi fi
echo "Quick commands:" echo "Quick commands:"
echo " mc-rcon 'op CursorBot' # Give operator" echo " mc-rcon 'op $USERNAME' # Give operator"
echo " mc-rcon 'gamemode creative' # Creative mode" echo " mc-rcon 'gamemode creative' # Creative mode"
echo " mc-stop $VERSION # Stop server" echo " mc-stop $VERSION # Stop server"

View file

@ -189,7 +189,58 @@ mcc-cmd() {
command="${command_parts[*]}" command="${command_parts[*]}"
printf '%s\n' "$command" >> "$input_file" printf '%s\n' "$command" >> "$input_file"
} }
mcc-kill() { pkill -f "MinecraftClient" 2>/dev/null && echo "MCC killed" || echo "No MCC process found"; tmux kill-session -t mcc-debug 2>/dev/null || true; } mcc-kill() {
local session=""
while [[ $# -gt 0 ]]; do
case "$1" in
--session)
shift
if [[ $# -eq 0 ]]; then
echo "mcc-kill: --session requires a value" >&2
return 1
fi
session="$1"
shift
;;
*)
echo "Unknown option: $1" >&2
return 1
;;
esac
done
session="$(_mcc_resolve_session "$session")"
local pid_file meta_file tmux_session pid
local killed=false
pid_file="$(_mcc_session_pid_file "$session")"
meta_file="$(_mcc_session_meta_file "$session")"
tmux_session="$(_mcc_tmux_session_name "$session")"
if [[ -f "$pid_file" ]]; then
pid="$(tr -cd '0-9' < "$pid_file")"
if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null || true
echo "Killed MCC PID $pid for session '$session'"
killed=true
else
echo "No live MCC PID found for session '$session' (pid file: $pid_file)"
fi
fi
if tmux has-session -t "$tmux_session" 2>/dev/null; then
tmux kill-session -t "$tmux_session" 2>/dev/null || true
echo "Killed tmux session '$tmux_session'"
killed=true
fi
if [[ -f "$pid_file" || -f "$meta_file" ]]; then
rm -f "$pid_file" "$meta_file"
fi
if [[ "$killed" == false ]]; then
echo "No MCC process or tmux session found for session '$session'"
fi
}
mcc-reload() { mcc-reload() {
mcc-kill mcc-kill
sleep 1 sleep 1

View file

@ -2,6 +2,7 @@
# Tail MCC and/or server logs side-by-side or individually. # Tail MCC and/or server logs side-by-side or individually.
# Usage: # Usage:
# tools/mcc-log-tail.sh # tail MCC log only # tools/mcc-log-tail.sh # tail MCC log only
# tools/mcc-log-tail.sh --session NAME # tail MCC log for a specific session
# tools/mcc-log-tail.sh --server VER # tail both MCC and server logs # tools/mcc-log-tail.sh --server VER # tail both MCC and server logs
# tools/mcc-log-tail.sh --server-only VER # tail server log only # tools/mcc-log-tail.sh --server-only VER # tail server log only
set -euo pipefail set -euo pipefail
@ -11,21 +12,25 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# shellcheck source=tools/mcc-env.sh # shellcheck source=tools/mcc-env.sh
source "$REPO_ROOT/tools/mcc-env.sh" source "$REPO_ROOT/tools/mcc-env.sh"
MCC_LOG="${TMPDIR:-/tmp}/mcc-debug/mcc-debug.log" SESSION=""
SERVER_VER="" SERVER_VER=""
SERVER_ONLY=false SERVER_ONLY=false
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
--session) SESSION="$2"; shift 2 ;;
--server) SERVER_VER="$2"; shift 2 ;; --server) SERVER_VER="$2"; shift 2 ;;
--server-only) SERVER_ONLY=true; SERVER_VER="$2"; shift 2 ;; --server-only) SERVER_ONLY=true; SERVER_VER="$2"; shift 2 ;;
-h|--help) -h|--help)
echo "Usage: tools/mcc-log-tail.sh [--server VER] [--server-only VER]" echo "Usage: tools/mcc-log-tail.sh [--session NAME] [--server VER] [--server-only VER]"
exit 0 ;; exit 0 ;;
*) echo "Unknown option: $1"; exit 1 ;; *) echo "Unknown option: $1"; exit 1 ;;
esac esac
done done
SESSION="$(_mcc_resolve_session "$SESSION")"
MCC_LOG="$(_mcc_session_log_file "$SESSION")"
if $SERVER_ONLY; then if $SERVER_ONLY; then
if [[ -z "$SERVER_VER" ]]; then if [[ -z "$SERVER_VER" ]]; then
echo "Specify server version with --server-only VER" >&2 echo "Specify server version with --server-only VER" >&2
@ -39,16 +44,17 @@ fi
if [[ -n "$SERVER_VER" ]]; then if [[ -n "$SERVER_VER" ]]; then
SERVER_LOG="$MCC_SERVERS/$SERVER_VER/logs/latest.log" SERVER_LOG="$MCC_SERVERS/$SERVER_VER/logs/latest.log"
echo "=== Tailing MCC + server logs ===" echo "=== Tailing MCC + server logs ==="
echo " Session: $SESSION"
echo " MCC: $MCC_LOG" echo " MCC: $MCC_LOG"
echo " Server: $SERVER_LOG" echo " Server: $SERVER_LOG"
echo "" echo ""
tail -f "$MCC_LOG" "$SERVER_LOG" 2>/dev/null tail -f "$MCC_LOG" "$SERVER_LOG" 2>/dev/null
else else
if [[ ! -f "$MCC_LOG" ]]; then if [[ ! -f "$MCC_LOG" ]]; then
echo "No MCC log found at $MCC_LOG" echo "No MCC log found for session '$SESSION' at $MCC_LOG"
echo "Start MCC first with: tools/mcc-debug.sh --file-input" echo "Start MCC first with: tools/mcc-debug.sh --session $SESSION --file-input"
exit 1 exit 1
fi fi
echo "=== Tailing MCC log: $MCC_LOG ===" echo "=== Tailing MCC log for session '$SESSION': $MCC_LOG ==="
exec tail -f "$MCC_LOG" exec tail -f "$MCC_LOG"
fi fi