From be849ed6849d757d3795615312c0488d5e0aabdb Mon Sep 17 00:00:00 2001 From: FailedProxy Date: Fri, 27 Mar 2026 17:39:36 +0000 Subject: [PATCH] reverted back before framework change --- common.sh | 265 ++++++++++++++++---------------- unRAID Essentials/rsync_stop.sh | 46 +++--- 2 files changed, 154 insertions(+), 157 deletions(-) diff --git a/common.sh b/common.sh index 956638d..3fe28f6 100644 --- a/common.sh +++ b/common.sh @@ -3,108 +3,20 @@ # ----------------- UNRAID OPS COMMON LIBRARY (CORE FRAMEWORK v1) ------------------------------- # ----------------------------------------------------------------------------------------------- -# ----------------------------- DEFAULT STATE ----------------------------- +# OUTPUT HELPERS +info() { echo "[INFO] $*"; } +warn() { echo "[WARN] $*"; } +error() { echo "[ERROR] $*"; exit 1; } +log() { [[ "${ENABLE_LOGGING:-false}" == true ]] && echo "[LOG] $*"; } + +# DEFAULT FLAGS DRY_RUN=${DRY_RUN:-false} ENABLE_LOGGING=${ENABLE_LOGGING:-false} SHOW_STATUS=${SHOW_STATUS:-false} -POSITIONAL_ARGS=() -ARGS_PARSED=false - -# ---------------------------------------------------------------------------------------------- -# ICONS -# ---------------------------------------------------------------------------------------------- - -ICON_INFO="🟢" -ICON_WARN="🟡" -ICON_ERROR="🔴" -ICON_LOG="⚪" -ICON_OK="✅" -ICON_RUN="🚀" -ICON_ARROW="➜" - -# ---------------------------------------------------------------------------------------------- -# OUTPUT LAYERS (RESTORED echo + log clarity) -# ---------------------------------------------------------------------------------------------- - -info() { echo -e "$ICON_INFO [INFO] $*"; } -warn() { echo -e "$ICON_WARN [WARN] $*"; } -error() { echo -e "$ICON_ERROR [ERROR] $*"; } -ok() { echo -e "$ICON_OK [OK] $*"; } - -log() { - if [[ "$ENABLE_LOGGING" == true ]]; then - echo -e "$ICON_LOG [LOG] $*" - fi -} - -echo_info() { - echo "[INFO] $*" -} - -echo_warn() { - echo "[WARN] $*" -} - -echo_error() { - echo "[ERROR] $*" -} - -# ---------------------------------------------------------------------------------------------- -# UI LAYER -# ---------------------------------------------------------------------------------------------- - -ui_header() { - echo - echo "==================================================" - echo " $ICON_RUN $*" - echo "==================================================" -} - -ui_section() { - echo - echo "--------------------------------------------------" - echo " $ICON_ARROW $*" - echo "--------------------------------------------------" -} - -ui_kv() { - printf " %-18s %s\n" "$1:" "$2" -} - -ui_status() { - case "$1" in - ok) echo "$ICON_OK [OK] $2" ;; - warn) echo "$ICON_WARN [WARN] $2" ;; - error) echo "$ICON_ERROR [ERROR] $2" ;; - *) echo "$ICON_INFO [INFO] $2" ;; - esac -} - -ui_footer() { - echo - echo "==================================================" - echo " $ICON_OK $*" - echo "==================================================" -} - -# ---------------------------------------------------------------------------------------------- -# ARG PARSER (FIXED + SAFE GUARD) -# ---------------------------------------------------------------------------------------------- - +# ARGUMENT PARSER parse_args() { - # Prevent double execution (THIS FIXES YOUR BUG) - if [[ "$ARGS_PARSED" == true ]]; then - log "parse_args skipped (already executed)" - return - fi - - ARGS_PARSED=true - POSITIONAL_ARGS=() - - log "Parsing arguments: $*" - for ARG in "$@"; do if [[ "$ARG" == *=* ]]; then @@ -113,20 +25,16 @@ parse_args() { case "$VAR_NAME" in LOG) - if [[ "$VAR_VALUE" == "true" ]]; then - ENABLE_LOGGING=true - echo_info "Logging enabled" - else - ENABLE_LOGGING=false - echo_info "Logging disabled" - fi + [[ "$VAR_VALUE" == "true" ]] && ENABLE_LOGGING=true + [[ "$VAR_VALUE" == "false" ]] && ENABLE_LOGGING=false + log "Logging set to $ENABLE_LOGGING" ;; *) if declare -p "$VAR_NAME" &>/dev/null; then printf -v "$VAR_NAME" '%s' "$VAR_VALUE" - log "Override $VAR_NAME=$VAR_VALUE" + log "Override $VAR_NAME -> $VAR_VALUE" else - echo_warn "Unknown variable: $VAR_NAME" + warn "Unknown variable: $VAR_NAME" fi ;; esac @@ -135,68 +43,153 @@ parse_args() { case "$ARG" in --dry-run|-n) DRY_RUN=true - echo_info "Dry-run enabled" + info "Dry-run enabled" ;; - --log) ENABLE_LOGGING=true - echo_info "Logging enabled" + info "Logging enabled" ;; - --no-log) ENABLE_LOGGING=false ;; - --status|--summary) SHOW_STATUS=true ;; - --help|-h) - echo "Usage: script [options] [SOURCE DEST]" + echo "Usage: script [--dry-run|-n] [--log] [--status] [VAR=value]" exit 0 ;; - *) - POSITIONAL_ARGS+=("$ARG") - echo_info "Positional arg: $ARG" - log "Stored positional: $ARG" + warn "Unknown argument: $ARG" ;; esac fi - done } -# ---------------------------------------------------------------------------------------------- # VALIDATION -# ---------------------------------------------------------------------------------------------- - require_var() { local var="$1" - if [[ -z "${!var:-}" ]]; then - echo_error "Missing required variable: $var" - exit 1 - fi + [[ -z "${!var:-}" ]] && error "Missing required variable: $var" } validate_int() { local name="$1" local value="$2" - if ! [[ "$value" =~ ^[0-9]+$ ]]; then - echo_error "$name must be integer" - exit 1 + [[ ! "${value:-}" =~ ^[0-9]+$ ]] && error "$name must be an integer" +} + +# HOST DETECTION +detect_hosts() { + + LOCAL_HOSTNAME="$(hostname)" + + if [[ "$LOCAL_HOSTNAME" == "$HOST1" ]]; then + LOCAL_SERVER_NAME="$HOST1" + REMOTE_SERVER_NAME="$HOST2" + elif [[ "$LOCAL_HOSTNAME" == "$HOST2" ]]; then + LOCAL_SERVER_NAME="$HOST2" + REMOTE_SERVER_NAME="$HOST1" + else + error "Unknown host: $LOCAL_HOSTNAME" + fi + + declare -gA SSH_KEYS + + SSH_KEYS["$HOST1|$HOST2"]="$HOST1_SSH_KEY" + SSH_KEYS["$HOST2|$HOST1"]="$HOST2_SSH_KEY" + + KEY_ID="$LOCAL_SERVER_NAME|$REMOTE_SERVER_NAME" + SSH_KEY="${SSH_KEYS[$KEY_ID]:-}" + + [[ -z "$SSH_KEY" ]] && error "Missing SSH key for $KEY_ID" + + log "Host mapping: $LOCAL_SERVER_NAME -> $REMOTE_SERVER_NAME" +} + +# REMOTE RESOLUTION +resolve_remote_ip() { + + log "Resolving remote IP..." + + REMOTE_SERVER=$(tailscale ip -4 "$REMOTE_SERVER_NAME" 2>/dev/null) + + [[ -z "$REMOTE_SERVER" ]] && error "Failed to resolve IP for $REMOTE_SERVER_NAME" + + log "Remote IP: $REMOTE_SERVER" +} + +check_remote_online() { + ping -c 1 "$REMOTE_SERVER" &>/dev/null +} + +# SAFE SSH WRAPPER +ssh_exec() { + ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "$@" +} + +# CONTAINER CONTROL +RUNNING_CONTAINERS=() + +stop_containers() { + + [[ ${#CRITICAL_CONTAINER_NAMES[@]:-0} -eq 0 ]] && return + + RUNNING_CONTAINERS=() + + for container in "${CRITICAL_CONTAINER_NAMES[@]}"; do + + STATUS=$(ssh_exec "docker inspect -f '{{.State.Running}}' $container 2>/dev/null" || echo "false") + + if [[ "$STATUS" == "true" ]]; then + info "Stopping $container" + RUNNING_CONTAINERS+=("$container") + ssh_exec "docker stop $container" || warn "Failed to stop $container" + fi + done +} + +start_containers() { + + [[ ${#RUNNING_CONTAINERS[@]} -eq 0 ]] && return + + for container in "${RUNNING_CONTAINERS[@]}"; do + + if [[ " ${DELAYED_CONTAINERS[*]:-} " == *" $container "* ]]; then + info "Delaying $container ($CONTAINER_DELAY s)" + sleep "$CONTAINER_DELAY" + fi + + info "Starting $container" + ssh_exec "docker start $container" || warn "Failed to start $container" + done +} + +# RSYNC OPTS +get_rsync_opts() { + + if [[ -n "${PROFILE_RSYNC_OPTS[$PROFILE_NAME]:-}" ]]; then + IFS=' ' read -r -a RSYNC_OPTS <<< "${PROFILE_RSYNC_OPTS[$PROFILE_NAME]}" + log "Using profile rsync opts" + else + RSYNC_OPTS=("${DEFAULT_RSYNC_OPTS[@]:-}") + log "Using default rsync opts" fi } -# ---------------------------------------------------------------------------------------------- -# STATUS -# ---------------------------------------------------------------------------------------------- - +# STATUS OUTPUT show_status() { - echo "===== OPS STATUS =====" - echo "DryRun: $DRY_RUN" - echo "Log: $ENABLE_LOGGING" - echo "Args: ${POSITIONAL_ARGS[*]:-(none)}" - echo "======================" + + echo + echo "==================================================" + echo " RSYNC OPS STATUS" + echo "--------------------------------------------------" + echo " Local: $LOCAL_SERVER_NAME" + echo " Remote: $REMOTE_SERVER_NAME" + echo " IP: ${REMOTE_SERVER:-unset}" + echo " Dry Run: $DRY_RUN" + echo " Logging: $ENABLE_LOGGING" + echo " Profile: ${PROFILE_NAME:-default}" + echo "==================================================" } \ No newline at end of file diff --git a/unRAID Essentials/rsync_stop.sh b/unRAID Essentials/rsync_stop.sh index f66a10e..5b2551f 100644 --- a/unRAID Essentials/rsync_stop.sh +++ b/unRAID Essentials/rsync_stop.sh @@ -4,6 +4,7 @@ set -e # ------------------------ Stop all running Rsync processes for Unraid ------------------------- # ---------------------------------------------------------------------------------------------- + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../Master.conf" @@ -19,7 +20,7 @@ require_var "HOST2" detect_hosts resolve_remote_ip -# ----------------------------- POSITIONAL ----------------------------- +# ----------------------------- POSITIONAL MAP ----------------------------- SOURCE="${POSITIONAL_ARGS[0]:-}" DEST="${POSITIONAL_ARGS[1]:-}" @@ -33,31 +34,37 @@ fi # ----------------------------- HEADER ----------------------------- -echo -echo "==================================================" -echo " 🚀 RSYNC START" -echo "==================================================" +ui_header "RSYNC OPERATION" -echo "[INFO] Source: $SOURCE" -echo "[INFO] Destination: $DEST" -echo "[INFO] Remote: $REMOTE_SERVER_NAME ($REMOTE_SERVER)" -echo "[INFO] DryRun: $DRY_RUN" -echo +ui_section "Context" +ui_kv "Source" "$SOURCE" +ui_kv "Destination" "$DEST" +ui_kv "Remote" "$REMOTE_SERVER_NAME" +ui_kv "IP" "$REMOTE_SERVER" +ui_kv "Dry Run" "$DRY_RUN" # ----------------------------- VALIDATION ----------------------------- if [[ -z "$SOURCE" ]]; then - echo_error "Missing SOURCE" + echo_error "Missing SOURCE argument" exit 1 fi if [[ -z "$DEST" ]]; then - echo_error "Missing DEST" + echo_error "Missing DEST argument" exit 1 fi -echo "[OK] Validation passed" -log "Validation completed successfully" +ui_status ok "Validation passed" + +# ----------------------------- MIRROR MODE ----------------------------- + +if [[ "$SOURCE" == "$DEST" ]]; then + echo + echo "[INFO] Mirror mode detected (identical paths)" + echo "[INFO] Treating as cross-host sync of same structure" + log "Mirror mode active" +fi # ----------------------------- PRECHECK ----------------------------- @@ -72,7 +79,7 @@ echo "[OK] Remote reachable" stop_containers -# ----------------------------- RSYNC ----------------------------- +# ----------------------------- RSYNC EXECUTION ----------------------------- get_rsync_opts @@ -87,8 +94,8 @@ if [[ "$DRY_RUN" == true ]]; then RSYNC_CMD+=("--dry-run") fi -echo -echo "[RUN] Executing rsync..." +ui_section "Execution" +echo "[RUN] Starting rsync..." log "CMD: ${RSYNC_CMD[*]}" "${RSYNC_CMD[@]}" @@ -99,7 +106,4 @@ start_containers # ----------------------------- END ----------------------------- -echo -echo "==================================================" -echo " ✅ RSYNC COMPLETE" -echo "==================================================" \ No newline at end of file +ui_footer "RSYNC COMPLETE" \ No newline at end of file