Files
Varaverk/Orchestrators/array_start.sh
T
Gmer4LfeandClaude Sonnet 4.6 009820e981 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>
2026-05-08 19:28:21 -04:00

217 lines
10 KiB
Bash

#!/bin/bash
# ==============================================================================================
# ================================= Array Start Orchestrator ===================================
# ==============================================================================================
# Single entry point for "At Startup of Array" in the User Scripts plugin.
# Launches everything configured in ARRAY_START_SCRIPTS in master.conf.
# This script exits after launching all scripts — unRAID sees it complete normally.
#
# ── WHAT IT LAUNCHES ──────────────────────────────────────────────────────────────────────────
# Configured in master.conf ARRAY_START_SCRIPTS — no changes to this script ever needed.
# Current order (order matters — see below):
#
# ONE-SHOT (run and exit naturally):
# unRAID_Essentials/inotify_tuning.sh — raise inotify limits before containers start
# unRAID_Essentials/docker_syslog_filter.sh — suppress veth log noise before logs fill
# unRAID_Essentials/php_fpm_max_children.sh — WebGUI performance tuning
# Transcodes/ramdisk_setup.sh — create tmpfs + symlink before Emby starts
# Docker_Essentials/docker_network_connect.sh — ensure networks + container connections
#
# CONTINUOUS (run until array stops):
# unRAID_Essentials/system_watchdog.sh — system health monitor (last line of defense)
# Docker_Essentials/docker_watchdog.sh — container health monitor
# Fallback/fallback.sh — mutual failover monitor
#
# ── WHY ORDER MATTERS ─────────────────────────────────────────────────────────────────────────
# inotify_tuning.sh — must run BEFORE Code-Server and other containers start
# containers that start with low inotify limits keep them ✅
# docker_syslog_filter — must run BEFORE any container starts creating veth interfaces
# ramdisk_setup.sh — must run BEFORE Emby starts transcoding
# docker_network_connect — must run BEFORE watchdogs check container states
# system_watchdog.sh — before docker_watchdog (system > container priority)
# docker_watchdog.sh — before failover (containers must be healthy for failover)
# fallback.sh — last — needs everything else stable to make decisions
#
# ── ONE-SHOT vs CONTINUOUS DETECTION ─────────────────────────────────────────────────────────
# Script is launched in background with bash script.sh &
# After 1 second: if PID still alive → continuous (running in background)
# if PID dead + exit 0 → one-shot completed successfully
# if PID dead + exit N → failure
#
# ── SAFEGUARDS ────────────────────────────────────────────────────────────────────────────────
# Root check — all launched scripts require root
# acquire_lock — prevents duplicate array start launches
# detect_hosts() — MY_ID in notifications
# validate_unraid_cmd — notify validated before use
# chmod +x auto-fix — non-executable scripts fixed before launch
# Full path on failure — shows exact path for debugging
# notify on failures — alert if any script fails to launch
#
# ── CONFIGURATION (master.conf) ───────────────────────────────────────────────────────────────
# ARRAY_START_SCRIPTS — ordered list of scripts to launch at array start
#
# ── USAGE ─────────────────────────────────────────────────────────────────────────────────────
# array_start.sh — normal launch (called by User Scripts at array start)
# array_start.sh --dry-run — show what would be launched without launching
# array_start.sh --status — show configured scripts and their current state
# array_start.sh --log — verbose output per script
# ==============================================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ECOSYSTEM_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
source "$ECOSYSTEM_ROOT/load_config.sh"
parse_args "$@"
# ==============================================================================================
# ━━━ Setup ━━━
# ==============================================================================================
if [[ "$EUID" -ne 0 ]]; then
error "Must be run as root"
exit 1
fi
validate_unraid_cmd \
"/usr/local/emhttp/plugins/dynamix/scripts/notify" \
"" "" \
"unRAID notify script" || warn "unRAID notify script not found — native notifications disabled"
acquire_lock
detect_hosts
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — scripts will not be launched"
# ==============================================================================================
# ━━━ Status ━━━
# ==============================================================================================
if [[ "$SHOW_STATUS" == true ]]; then
echo ""
echo "━━━━━ $ICON_SUMMARY ARRAY START STATUS ━━━━━"
echo "$ICON_HOST Identity: $MY_ID ($LOCAL_SERVER_NAME)"
echo "$ICON_GEAR Scripts: ${#ARRAY_START_SCRIPTS[@]} configured"
echo ""
for relative_path in "${ARRAY_START_SCRIPTS[@]}"; do
[[ -z "$relative_path" ]] && continue
script_path="$ECOSYSTEM_ROOT/$relative_path"
script_name=$(basename "$script_path")
if [[ ! -f "$script_path" ]]; then
echo " $ICON_ERROR $script_name — FILE NOT FOUND"
echo " $script_path"
continue
fi
[[ ! -x "$script_path" ]] && flag=" (not executable — will auto-fix)" || flag=""
# Check if currently running
if pgrep -f "$script_path" >/dev/null 2>&1; then
RUN_PID=$(pgrep -f "$script_path" | head -1)
echo " $ICON_RUNNING $script_name — RUNNING (PID $RUN_PID)${flag}"
else
echo " $ICON_NOT_RUNNING $script_name — not running${flag}"
fi
done
echo "━━━━━━━━━━━━━━━━━━━━━━━"
exit 0
fi
# ==============================================================================================
# ━━━ Launch Scripts ━━━
# ==============================================================================================
echo ""
echo "━━━ $ICON_GEAR Array Start — $MY_ID$(date '+%Y-%m-%d %H:%M:%S') ━━━"
log "Ecosystem root: $ECOSYSTEM_ROOT"
log "Launching ${#ARRAY_START_SCRIPTS[@]} script(s)..."
echo ""
START=$(date +%s)
LAUNCHED=0
FAILED=0
FAILED_SCRIPTS=()
for relative_path in "${ARRAY_START_SCRIPTS[@]}"; do
[[ -z "$relative_path" ]] && continue
SCRIPT_PATH="$ECOSYSTEM_ROOT/$relative_path"
SCRIPT_NAME=$(basename "$SCRIPT_PATH")
# File existence check
if [[ ! -f "$SCRIPT_PATH" ]]; then
error "$SCRIPT_NAME — not found"
error " Expected: $SCRIPT_PATH"
(( FAILED++ ))
FAILED_SCRIPTS+=("$SCRIPT_NAME")
continue
fi
# Auto-fix permissions — chmod +x if needed
if [[ ! -x "$SCRIPT_PATH" ]]; then
warn "$SCRIPT_NAME — not executable, fixing..."
chmod +x "$SCRIPT_PATH" || {
error "$SCRIPT_NAME — chmod +x failed"
(( FAILED++ ))
FAILED_SCRIPTS+=("$SCRIPT_NAME")
continue
}
fi
if [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — would launch: $SCRIPT_NAME"
(( LAUNCHED++ ))
continue
fi
log "$ICON_START Launching $SCRIPT_NAME..."
bash "$SCRIPT_PATH" &
PID=$!
# Brief settle — 1s enough to detect immediate failures
sleep 1
if kill -0 "$PID" 2>/dev/null; then
# Still running → continuous script
warn "$SCRIPT_NAME — running (PID $PID) ✅"
(( LAUNCHED++ ))
else
# Exited — check if one-shot success or failure
wait "$PID"
EXIT_CODE=$?
if [[ "$EXIT_CODE" -eq 0 ]]; then
log "$SCRIPT_NAME — completed (one-shot) ✅"
(( LAUNCHED++ ))
else
error "$SCRIPT_NAME — exited with code $EXIT_CODE"
error " Path: $SCRIPT_PATH"
(( FAILED++ ))
FAILED_SCRIPTS+=("$SCRIPT_NAME")
fi
fi
done
END=$(date +%s)
# ==============================================================================================
# ━━━ Summary ━━━
# ==============================================================================================
echo ""
echo "━━━━━ $ICON_SUMMARY ARRAY START SUMMARY ━━━━━"
echo "$ICON_HOST Identity: $MY_ID ($LOCAL_SERVER_NAME)"
echo "$ICON_SUCCESS Launched: $LAUNCHED"
[[ "$FAILED" -gt 0 ]] && echo "$ICON_ERROR Failed: $FAILED${FAILED_SCRIPTS[*]}"
echo "$ICON_TIME Duration: $(format_duration $(( END - START )))"
echo ""
if [[ "$DRY_RUN" == true ]]; then
warn "DRY RUN — no scripts launched"
elif [[ "$FAILED" -gt 0 ]]; then
warn "Status: $FAILED script(s) failed — ${FAILED_SCRIPTS[*]}"
notify "Array start on $(hostname) ($MY_ID) — $FAILED script(s) failed: ${FAILED_SCRIPTS[*]}" \
"Array Start" "warning"
else
log "$ICON_DONE Status: all $LAUNCHED script(s) launched ✅"
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"