refactor: rename failover/HA → fallback across entire codebase
Removes all references to "failover" and "HA" (high availability) terminology from variable names, config keys, state values, rsync profile names, directory paths, and user-visible strings. Mapping: FAILOVER_* → FALLBACK_* FAILOVER_HOST*_RUNS_FOR → FALLBACK_HOST*_COVERS critical-failover → critical-fallback emby-failover → emby-fallback appdata-Failover/ → appdata-Fallback/ "FAILOVER" state value → "FALLBACK" failover_start key → fallback_start Failover/ directory → Fallback/ failover.sh → fallback.sh failover_state.db → fallback_state.db -Failover folder suffix → -Fallback State machine: NORMAL | FALLBACK | DARK (unchanged) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
4e22f5d1f7
commit
009820e981
Executable
+101
@@ -0,0 +1,101 @@
|
||||
#!/bin/bash
|
||||
# ==============================================================================================
|
||||
# ================================= Claude Code Startup ========================================
|
||||
# ==============================================================================================
|
||||
# Restores Claude Code's persistent data after an Unraid reboot and launches Claude.
|
||||
#
|
||||
# Unraid's root filesystem lives in RAM — /root/.claude and /root/.local are wiped on every
|
||||
# reboot. This script symlinks both directories back to persistent appdata storage before
|
||||
# launching Claude, so memory, sessions, and settings survive across reboots.
|
||||
#
|
||||
# ── FIRST RUN ─────────────────────────────────────────────────────────────────────────────────
|
||||
# If persistent storage has no data yet, migrates from the current live locations:
|
||||
# /root/.claude → PERSIST_DIR/.claude (memory, sessions, settings)
|
||||
# /root/.local/share/claude → PERSIST_DIR/local/share/claude (installed binaries)
|
||||
# Subsequent runs skip the migration and just create the symlinks.
|
||||
#
|
||||
# ── USAGE ─────────────────────────────────────────────────────────────────────────────────────
|
||||
# claude_startup.sh — set up persistent symlinks and launch Claude
|
||||
# claude_startup.sh --setup — set up only, do not launch (for array_start.sh use)
|
||||
# ==============================================================================================
|
||||
|
||||
PERSIST_DIR="/mnt/user/appdata/claude-code"
|
||||
CLAUDE_DATA="$PERSIST_DIR/.claude"
|
||||
CLAUDE_BIN="$PERSIST_DIR/local/share/claude"
|
||||
|
||||
LAUNCH=true
|
||||
[[ "$1" == "--setup" ]] && LAUNCH=false
|
||||
|
||||
# Standalone — no common.sh dependency
|
||||
_log() { echo " ✅ $*"; }
|
||||
_warn() { echo " ⚠️ $*"; }
|
||||
_err() { echo " ❌ $*" >&2; }
|
||||
|
||||
echo ""
|
||||
echo "━━━ Claude Code Startup ━━━"
|
||||
echo ""
|
||||
|
||||
# ── Array must be mounted ─────────────────────────────────────────────────────────────────────
|
||||
if ! mountpoint -q /mnt/user 2>/dev/null; then
|
||||
_err "Array not mounted — /mnt/user not available"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Create persistent dirs ────────────────────────────────────────────────────────────────────
|
||||
mkdir -p "$CLAUDE_DATA" "$CLAUDE_BIN"
|
||||
|
||||
# ── Migrate .claude on first run ──────────────────────────────────────────────────────────────
|
||||
if [[ ! -L /root/.claude && -d /root/.claude ]]; then
|
||||
_warn "First run — migrating /root/.claude → $CLAUDE_DATA"
|
||||
cp -a /root/.claude/. "$CLAUDE_DATA/"
|
||||
rm -rf /root/.claude
|
||||
_log "Migrated .claude (memory, sessions, settings)"
|
||||
elif [[ -z "$(ls -A "$CLAUDE_DATA" 2>/dev/null)" && -d /root/.claude ]]; then
|
||||
_warn "Persistent storage empty — copying current .claude data"
|
||||
cp -a /root/.claude/. "$CLAUDE_DATA/"
|
||||
_log "Copied .claude data to persistent storage"
|
||||
fi
|
||||
|
||||
# ── Migrate Claude binaries on first run ──────────────────────────────────────────────────────
|
||||
if [[ ! -L /root/.local/share/claude && -d /root/.local/share/claude ]]; then
|
||||
_warn "First run — migrating Claude binaries → $CLAUDE_BIN"
|
||||
cp -a /root/.local/share/claude/. "$CLAUDE_BIN/"
|
||||
_log "Migrated Claude binaries"
|
||||
fi
|
||||
|
||||
# ── Create symlinks ───────────────────────────────────────────────────────────────────────────
|
||||
# Remove any real directories first — ln -sfn silently creates inside a dir instead of
|
||||
# replacing it, which produces a circular symlink on subsequent runs after migration.
|
||||
mkdir -p /root/.local/share /root/.local/bin
|
||||
|
||||
[[ -d /root/.claude && ! -L /root/.claude ]] && rm -rf /root/.claude
|
||||
ln -sfn "$CLAUDE_DATA" /root/.claude
|
||||
_log ".claude → $CLAUDE_DATA"
|
||||
|
||||
[[ -d /root/.local/share/claude && ! -L /root/.local/share/claude ]] && rm -rf /root/.local/share/claude
|
||||
ln -sfn "$CLAUDE_BIN" /root/.local/share/claude
|
||||
_log "claude binary → $CLAUDE_BIN"
|
||||
|
||||
# ── Point the claude binary at the latest installed version ───────────────────────────────────
|
||||
LATEST=$(ls "$CLAUDE_BIN/versions/" 2>/dev/null | sort -V | tail -1)
|
||||
if [[ -z "$LATEST" ]]; then
|
||||
_err "No Claude versions found in $CLAUDE_BIN/versions/"
|
||||
_err "Install Claude Code first: npm install -g @anthropic-ai/claude-code"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ln -sfn "$CLAUDE_BIN/versions/$LATEST" /root/.local/bin/claude
|
||||
_log "claude v$LATEST ready"
|
||||
|
||||
echo ""
|
||||
|
||||
# ── Setup-only mode (used by array_start.sh or other callers) ─────────────────────────────────
|
||||
if [[ "$LAUNCH" == false ]]; then
|
||||
_log "Setup complete — run 'claude' to start"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── Launch ────────────────────────────────────────────────────────────────────────────────────
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
exec claude
|
||||
@@ -2,22 +2,22 @@
|
||||
# ==============================================================================================
|
||||
# ============================= Failover State Reset ===========================================
|
||||
# ==============================================================================================
|
||||
# Resets the failover state file to NORMAL and clears all tier flags.
|
||||
# Use when the failover state file is stuck in a non-NORMAL state after:
|
||||
# Resets the fallback state file to NORMAL and clears all tier flags.
|
||||
# Use when the fallback state file is stuck in a non-NORMAL state after:
|
||||
# - Failover testing that left state as FAILOVER
|
||||
# - A failed handback that did not complete cleanly
|
||||
# - Manual intervention that left state inconsistent
|
||||
# - failover.sh was killed mid-cycle and state is unknown
|
||||
# - fallback.sh was killed mid-cycle and state is unknown
|
||||
#
|
||||
# ── WHAT THIS DOES ────────────────────────────────────────────────────────────────────────────
|
||||
# Writes a fresh state file with:
|
||||
# state=NORMAL
|
||||
# failover_start=0
|
||||
# fallback_start=0
|
||||
# handback_strikes=0
|
||||
# tier2_started=false / tier3_started=false / tier4_started=false
|
||||
#
|
||||
# Does NOT start or stop any containers — state file only.
|
||||
# After reset, failover.sh will resume from NORMAL on its next cycle.
|
||||
# After reset, fallback.sh will resume from NORMAL on its next cycle.
|
||||
#
|
||||
# ── ⚠️ ONLY RUN WHEN SAFE ────────────────────────────────────────────────────────────────────
|
||||
# Verify BEFORE resetting:
|
||||
@@ -26,22 +26,22 @@
|
||||
# ✓ No active failover actually in progress
|
||||
# ✓ Both servers can see each other
|
||||
#
|
||||
# Resetting state while a real failover is happening causes failover.sh to stop
|
||||
# Resetting state while a real fallback is happening causes fallback.sh to stop
|
||||
# covering the remote server — services go offline until next detection cycle.
|
||||
#
|
||||
# ── SAFEGUARDS ────────────────────────────────────────────────────────────────────────────────
|
||||
# failover.sh running check — warns if failover.sh is active when reset is attempted
|
||||
# fallback.sh running check — warns if fallback.sh is active when reset is attempted
|
||||
# acquire_lock — prevents concurrent resets
|
||||
# flock on state write — prevents race with failover.sh mid-cycle read
|
||||
# flock on state write — prevents race with fallback.sh mid-cycle read
|
||||
# Confirmation required — interactive: type YES | non-interactive: --force flag
|
||||
# validate_unraid_cmd — notify validated before use
|
||||
#
|
||||
# ── USAGE ─────────────────────────────────────────────────────────────────────────────────────
|
||||
# failover_state_reset.sh — interactive reset (prompts for YES)
|
||||
# failover_state_reset.sh --dry-run — show current state, show what would be written
|
||||
# failover_state_reset.sh --status — show current state file contents and exit
|
||||
# failover_state_reset.sh --force — non-interactive reset (no prompt, use in scripts)
|
||||
# failover_state_reset.sh --force --dry-run — dry run without prompt
|
||||
# fallback_state_reset.sh — interactive reset (prompts for YES)
|
||||
# fallback_state_reset.sh --dry-run — show current state, show what would be written
|
||||
# fallback_state_reset.sh --status — show current state file contents and exit
|
||||
# fallback_state_reset.sh --force — non-interactive reset (no prompt, use in scripts)
|
||||
# fallback_state_reset.sh --force --dry-run — dry run without prompt
|
||||
# ==============================================================================================
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
@@ -85,31 +85,31 @@ detect_hosts
|
||||
# ━━━ Current State ━━━
|
||||
# ==============================================================================================
|
||||
echo ""
|
||||
echo "━━━ $ICON_FAILOVER Current Failover State ━━━"
|
||||
echo "━━━ $ICON_FALLBACK Current Fallback State ━━━"
|
||||
echo "$ICON_HOST My ID: $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
echo ""
|
||||
|
||||
if [[ ! -f "$FAILOVER_STATE_FILE" ]]; then
|
||||
warn "State file not found: $FAILOVER_STATE_FILE"
|
||||
if [[ ! -f "$FALLBACK_STATE_FILE" ]]; then
|
||||
warn "State file not found: $FALLBACK_STATE_FILE"
|
||||
warn "Will be created fresh on reset"
|
||||
CURRENT_STATE="NOT FOUND"
|
||||
else
|
||||
log "State file: $FAILOVER_STATE_FILE"
|
||||
log "State file: $FALLBACK_STATE_FILE"
|
||||
echo ""
|
||||
while IFS='=' read -r key value; do
|
||||
[[ -z "$key" ]] && continue
|
||||
echo " $ICON_INFO $key = $value"
|
||||
done < "$FAILOVER_STATE_FILE"
|
||||
CURRENT_STATE=$(grep "^state=" "$FAILOVER_STATE_FILE" 2>/dev/null | cut -d= -f2)
|
||||
done < "$FALLBACK_STATE_FILE"
|
||||
CURRENT_STATE=$(grep "^state=" "$FALLBACK_STATE_FILE" 2>/dev/null | cut -d= -f2)
|
||||
fi
|
||||
|
||||
if [[ "$SHOW_STATUS" == true ]]; then
|
||||
echo ""
|
||||
# Check if failover.sh is running — informational in status mode
|
||||
if pgrep -f "failover.sh" >/dev/null 2>&1; then
|
||||
warn "failover.sh is currently RUNNING — any reset would race with active cycle"
|
||||
# Check if fallback.sh is running — informational in status mode
|
||||
if pgrep -f "fallback.sh" >/dev/null 2>&1; then
|
||||
warn "fallback.sh is currently RUNNING — any reset would race with active cycle"
|
||||
else
|
||||
log "failover.sh is not running"
|
||||
log "fallback.sh is not running"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
@@ -120,18 +120,18 @@ fi
|
||||
echo ""
|
||||
echo "━━━ $ICON_SHIELD Safety Checks ━━━"
|
||||
|
||||
# Check if failover.sh is actively running
|
||||
FAILOVER_RUNNING=false
|
||||
if pgrep -f "failover.sh" >/dev/null 2>&1; then
|
||||
FAILOVER_RUNNING=true
|
||||
warn "⚠️ failover.sh is currently RUNNING"
|
||||
# Check if fallback.sh is actively running
|
||||
FALLBACK_RUNNING=false
|
||||
if pgrep -f "fallback.sh" >/dev/null 2>&1; then
|
||||
FALLBACK_RUNNING=true
|
||||
warn "⚠️ fallback.sh is currently RUNNING"
|
||||
warn "Resetting state mid-cycle may cause incorrect decisions on the next iteration"
|
||||
warn "Consider stopping failover.sh first (click Abort in User Scripts)"
|
||||
warn "Then reset state, then restart failover.sh"
|
||||
warn "Consider stopping fallback.sh first (click Abort in User Scripts)"
|
||||
warn "Then reset state, then restart fallback.sh"
|
||||
echo ""
|
||||
warn "If you are sure you want to proceed anyway, confirm below"
|
||||
else
|
||||
log "failover.sh is not running — safe to reset ✅"
|
||||
log "fallback.sh is not running — safe to reset ✅"
|
||||
fi
|
||||
|
||||
# Check current state — if already NORMAL warn user
|
||||
@@ -144,11 +144,11 @@ fi
|
||||
# ━━━ Confirmation ━━━
|
||||
# ==============================================================================================
|
||||
echo ""
|
||||
warn "This will reset failover state to NORMAL on $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
warn "This will reset fallback state to NORMAL on $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
warn "Verify before proceeding:"
|
||||
warn " ✓ Right containers running on the right server"
|
||||
warn " ✓ DDNS pointing at correct server"
|
||||
warn " ✓ No real failover actually in progress"
|
||||
warn " ✓ No real fallback actually in progress"
|
||||
warn " ✓ Both servers can reach each other"
|
||||
echo ""
|
||||
|
||||
@@ -165,7 +165,7 @@ if [[ "$DRY_RUN" == false ]]; then
|
||||
else
|
||||
# Non-interactive — no terminal, cannot prompt
|
||||
error "Non-interactive mode — use --force flag to skip confirmation"
|
||||
error "Usage: failover_state_reset.sh --force"
|
||||
error "Usage: fallback_state_reset.sh --force"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
@@ -174,10 +174,10 @@ fi
|
||||
# ━━━ Reset State File ━━━
|
||||
# ==============================================================================================
|
||||
echo ""
|
||||
echo "━━━ $ICON_FAILOVER Resetting State File ━━━"
|
||||
echo "━━━ $ICON_FALLBACK Resetting State File ━━━"
|
||||
|
||||
NEW_STATE_CONTENT="state=NORMAL
|
||||
failover_start=0
|
||||
fallback_start=0
|
||||
handback_strikes=0
|
||||
tier2_started=false
|
||||
tier3_started=false
|
||||
@@ -186,31 +186,31 @@ last_reset=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
reset_by=$MY_ID"
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
warn "DRY RUN — would write to $FAILOVER_STATE_FILE:"
|
||||
warn "DRY RUN — would write to $FALLBACK_STATE_FILE:"
|
||||
echo ""
|
||||
echo "$NEW_STATE_CONTENT" | while IFS= read -r line; do
|
||||
echo " $line"
|
||||
done
|
||||
else
|
||||
mkdir -p "$(dirname "$FAILOVER_STATE_FILE")"
|
||||
mkdir -p "$(dirname "$FALLBACK_STATE_FILE")"
|
||||
|
||||
# flock prevents race with failover.sh mid-cycle read/write
|
||||
# flock prevents race with fallback.sh mid-cycle read/write
|
||||
(
|
||||
flock -x 200
|
||||
echo "$NEW_STATE_CONTENT" > "$FAILOVER_STATE_FILE"
|
||||
) 200>"${FAILOVER_STATE_FILE}.lock"
|
||||
echo "$NEW_STATE_CONTENT" > "$FALLBACK_STATE_FILE"
|
||||
) 200>"${FALLBACK_STATE_FILE}.lock"
|
||||
|
||||
warn "State file reset to NORMAL ✅"
|
||||
log "Written to: $FAILOVER_STATE_FILE"
|
||||
log "Written to: $FALLBACK_STATE_FILE"
|
||||
fi
|
||||
|
||||
# ==============================================================================================
|
||||
# ━━━ Summary ━━━
|
||||
# ==============================================================================================
|
||||
echo ""
|
||||
echo "━━━━━ $ICON_SUMMARY FAILOVER STATE RESET SUMMARY ━━━━━"
|
||||
echo "━━━━━ $ICON_SUMMARY FALLBACK STATE RESET SUMMARY ━━━━━"
|
||||
echo "$ICON_HOST Identity: $MY_ID ($LOCAL_SERVER_NAME)"
|
||||
echo "$ICON_FAILOVER File: $FAILOVER_STATE_FILE"
|
||||
echo "$ICON_FALLBACK File: $FALLBACK_STATE_FILE"
|
||||
echo "$ICON_TIME Reset at: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||
echo ""
|
||||
|
||||
@@ -218,12 +218,12 @@ if [[ "$DRY_RUN" == true ]]; then
|
||||
warn "DRY RUN — no changes made"
|
||||
else
|
||||
warn "$ICON_DONE State reset to NORMAL"
|
||||
log "failover.sh will resume from NORMAL on next cycle"
|
||||
log "fallback.sh will resume from NORMAL on next cycle"
|
||||
log "No containers were started or stopped"
|
||||
echo ""
|
||||
[[ "$FAILOVER_RUNNING" == true ]] && \
|
||||
warn "⚠️ failover.sh was running during reset — monitor next cycle carefully"
|
||||
notify "Failover state manually reset to NORMAL on $(hostname) ($MY_ID)" \
|
||||
"Failover State Reset" "warning"
|
||||
[[ "$FALLBACK_RUNNING" == true ]] && \
|
||||
warn "⚠️ fallback.sh was running during reset — monitor next cycle carefully"
|
||||
notify "Fallback state manually reset to NORMAL on $(hostname) ($MY_ID)" \
|
||||
"Fallback State Reset" "warning"
|
||||
fi
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
Reference in New Issue
Block a user