From 5d23bf7f58fce959eeb8dd8df50290e2ebe3ee96 Mon Sep 17 00:00:00 2001 From: FailedProxy Date: Tue, 24 Mar 2026 20:46:21 +0000 Subject: [PATCH] Fuck --- Rsync/rsync.sh | 143 ++++++++++++------------------------------------- common.sh | 31 +++-------- 2 files changed, 41 insertions(+), 133 deletions(-) diff --git a/Rsync/rsync.sh b/Rsync/rsync.sh index a10a2a5..5c9cbb7 100644 --- a/Rsync/rsync.sh +++ b/Rsync/rsync.sh @@ -1,19 +1,13 @@ #!/bin/bash set -e -#----------------------------------------------------------------------------------------------- -# --------------------------- Core Rsync Script for Unraid ------------------------------------- -#----------------------------------------------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../common.sh" # Load config load_master_conf -# Detect hosts and SSH key -detect_hosts - -# Input arguments +# Input directory DIRECTORY="$1" if [[ -z "$DIRECTORY" ]]; then echo "Usage: $0 [--dry-run|-n] [VAR=value ...]" @@ -22,11 +16,15 @@ fi shift parse_args "$@" +# Detect hosts & SSH key +detect_hosts + # Determine profile -PROFILE_NAME=$(basename "$DIRECTORY" | tr '[:upper:]' '[:lower:]') +DIR_CLEAN="${DIRECTORY%/}" +PROFILE_NAME=$(basename "$DIR_CLEAN" | tr '[:upper:]' '[:lower:]') echo "Detected profile: $PROFILE_NAME" -# Apply profile settings +# Apply profile defaults MAX_RSYNC_PROCS=${PROFILE_MAX_PROCS[$PROFILE_NAME]:-$MAX_RSYNC_PROCS} BW_LIMIT=${PROFILE_BW_LIMIT[$PROFILE_NAME]:-$BW_LIMIT} CRITICAL_CONTAINER_NAMES=(${PROFILE_CRITICAL_CONTAINER_NAMES[$PROFILE_NAME]}) @@ -36,7 +34,7 @@ RETRY_COUNT=${PROFILE_RETRY_COUNT[$PROFILE_NAME]:-$RETRY_COUNT} SLEEP=${PROFILE_SLEEP[$PROFILE_NAME]:-$SLEEP} EXCLUDE_DIRS=(${PROFILE_EXCLUDE_DIRS[$PROFILE_NAME]:-${EXCLUDE_DIRS[@]}}) -# Validate numeric variables +# Validate validate_int MAX_RSYNC_PROCS "$MAX_RSYNC_PROCS" validate_int BW_LIMIT "$BW_LIMIT" validate_int CONTAINER_DELAY "$CONTAINER_DELAY" @@ -45,129 +43,56 @@ validate_int SLEEP "$SLEEP" echo "Settings: MAX_RSYNC_PROCS=$MAX_RSYNC_PROCS, BW_LIMIT=$BW_LIMIT, CONTAINERS=${CRITICAL_CONTAINER_NAMES[*]}, EXCLUDES=${EXCLUDE_DIRS[*]}" -#----------------------------------------------------------------------------------------------- -# --------------------------- Dependency Check -------------------------------------------------- -#----------------------------------------------------------------------------------------------- -for cmd in rsync ssh ping timeout docker tailscale; do - command -v "$cmd" >/dev/null 2>&1 || { echo "Error: Required command '$cmd' is not installed."; exit 1; } -done - -trap 'echo "Script interrupted. Exiting."; exit 130' INT TERM - -#----------------------------------------------------------------------------------------------- -# --------------------------- Helper Functions ------------------------------------------------- -#----------------------------------------------------------------------------------------------- -wait_for_rsync() { - for attempt in $(seq 1 "$RETRY_COUNT"); do - RSYNC_COUNT=$(pgrep -fc "rsync.*root@${REMOTE_SERVER}" || true) - if [ "$RSYNC_COUNT" -ge "$MAX_RSYNC_PROCS" ]; then - echo "[$LOCAL_SERVER_NAME] Waiting... ($RSYNC_COUNT active rsync processes)" - sleep "$SLEEP" - else - return 0 - fi - done - echo "Too many rsync processes, exiting." - exit 1 -} - -check_server_online() { - timeout 5 ping -c 1 "$REMOTE_SERVER" &>/dev/null -} - -declare -a RUNNING_CONTAINERS=() - -stop_containers() { - echo "[$LOCAL_SERVER_NAME] Checking containers on ${REMOTE_SERVER_NAME}..." - RUNNING_CONTAINERS=() - for container in "${CRITICAL_CONTAINER_NAMES[@]}"; do - STATUS=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ - "docker inspect -f '{{.State.Running}}' $container 2>/dev/null" || echo "false") - if [ "$STATUS" == "true" ]; then - echo "Stopping $container" - RUNNING_CONTAINERS+=("$container") - if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would stop container $container" - else - ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker stop $container" - fi - fi - done -} - -start_containers() { - echo "[$LOCAL_SERVER_NAME] Restarting containers on ${REMOTE_SERVER_NAME}..." - for container in "${RUNNING_CONTAINERS[@]}"; do - if [[ " ${DELAYED_CONTAINERS[*]} " == *" $container "* ]]; then - echo "Delaying start of $container by ${CONTAINER_DELAY}s..." - [ "$DRY_RUN" = false ] && sleep "$CONTAINER_DELAY" - fi - if [ "$DRY_RUN" = true ]; then - echo "[DRY-RUN] Would start container $container" - else - ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker start $container" - fi - done -} - -#----------------------------------------------------------------------------------------------- -# --------------------------- Main Rsync Logic ------------------------------------------------- -#----------------------------------------------------------------------------------------------- +# Main rsync function main() { echo "[$LOCAL_SERVER_NAME] Syncing $DIRECTORY → $REMOTE_SERVER:$DIRECTORY" + # Retry server ping for i in $(seq 1 "$RETRY_COUNT"); do - if check_server_online; then break; fi + if timeout 5 ping -c1 "$REMOTE_SERVER" &>/dev/null; then break; fi echo "Remote $REMOTE_SERVER_NAME down, retrying in $SLEEP seconds..." sleep "$SLEEP" done + timeout 5 ping -c1 "$REMOTE_SERVER" &>/dev/null || { echo "Remote $REMOTE_SERVER_NAME unreachable"; exit 1; } - check_server_online || { echo "Remote $REMOTE_SERVER_NAME unreachable. Exiting."; exit 1; } - - wait_for_rsync - stop_containers - - RSYNC_OPTS=( - -av - --info=progress2 - --human-readable - --bwlimit="$BW_LIMIT" - --delete - --inplace - --no-whole-file - ) + # Stop critical containers + RUNNING_CONTAINERS=() + for container in "${CRITICAL_CONTAINER_NAMES[@]}"; do + STATUS=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker inspect -f '{{.State.Running}}' $container" 2>/dev/null || echo "false") + if [[ "$STATUS" == "true" ]]; then + echo "Stopping $container" + RUNNING_CONTAINERS+=("$container") + [ "$DRY_RUN" = false ] && ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker stop $container" + fi + done + # Rsync + RSYNC_OPTS=(-av --info=progress2 --human-readable --bwlimit="$BW_LIMIT" --delete --inplace --no-whole-file) for pattern in "${EXCLUDE_DIRS[@]}"; do RSYNC_OPTS+=(--exclude="$pattern") done - [ "$DRY_RUN" = true ] && RSYNC_OPTS+=("--dry-run") for attempt in $(seq 1 "$RETRY_COUNT"); do echo "Starting rsync attempt $attempt/$RETRY_COUNT..." - if rsync "${RSYNC_OPTS[@]}" \ - -e "ssh -i \"$SSH_KEY\" -T -o Compression=no -o IPQoS=throughput" \ - "$DIRECTORY" "root@${REMOTE_SERVER}:$DIRECTORY"; then + if rsync "${RSYNC_OPTS[@]}" -e "ssh -i \"$SSH_KEY\" -T -o Compression=no -o IPQoS=throughput" "$DIRECTORY" "root@${REMOTE_SERVER}:$DIRECTORY"; then echo "Rsync completed successfully." break else echo "Rsync attempt $attempt failed." - if [[ "$attempt" -lt "$RETRY_COUNT" ]]; then - echo "Retrying in $SLEEP seconds..." - sleep "$SLEEP" - else - echo "All $RETRY_COUNT rsync attempts failed." - start_containers - exit 1 - fi + [ "$attempt" -lt "$RETRY_COUNT" ] && sleep "$SLEEP" || { echo "All attempts failed"; exit 1; } fi done - start_containers + # Restart containers + for container in "${RUNNING_CONTAINERS[@]}"; do + if [[ " ${DELAYED_CONTAINERS[*]} " == *" $container "* ]]; then + [ "$DRY_RUN" = false ] && sleep "$CONTAINER_DELAY" + fi + [ "$DRY_RUN" = false ] && ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker start $container" + done + echo "[$LOCAL_SERVER_NAME] Sync complete." } -#----------------------------------------------------------------------------------------------- -# --------------------------- Execute --------------------------------------------------------- -#----------------------------------------------------------------------------------------------- main \ No newline at end of file diff --git a/common.sh b/common.sh index 90a3543..d36226f 100644 --- a/common.sh +++ b/common.sh @@ -14,20 +14,13 @@ #----------------------------------------------------------------------------------------------- # Load Master.conf reliably #----------------------------------------------------------------------------------------------- +# Load Master.conf load_master_conf() { - # Determine the directory of THIS file (common.sh) local script_dir script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local master_conf="$script_dir/../Master.conf" - # Master.conf is assumed to be in the parent directory of unRAID scripts root - # i.e., one level up from where common.sh lives - local master_conf="$script_dir/Master.conf" - if [ ! -f "$master_conf" ]; then - # fallback for Rsync/rsync.sh calling common.sh - master_conf="$script_dir/../Master.conf" - fi - - if [ -f "$master_conf" ]; then + if [[ -f "$master_conf" ]]; then source "$master_conf" echo "Loaded Master.conf from $master_conf" else @@ -36,12 +29,9 @@ load_master_conf() { fi } -#----------------------------------------------------------------------------------------------- -# Parse CLI args -#----------------------------------------------------------------------------------------------- +# Parse CLI arguments (flags + VAR=value overrides) parse_args() { DRY_RUN=${DRY_RUN:-false} - for ARG in "$@"; do if [[ "$ARG" == *=* ]]; then local VAR_NAME="${ARG%%=*}" @@ -58,16 +48,13 @@ parse_args() { --help|-h) echo "Usage: script [--dry-run|-n] [VAR=value ...]" exit 0 ;; - *) - echo "Warning: Unknown argument $ARG" ;; + *) echo "Warning: Unknown argument $ARG" ;; esac fi done } -#----------------------------------------------------------------------------------------------- # Validate integer -#----------------------------------------------------------------------------------------------- validate_int() { local name="$1" local value="$2" @@ -77,9 +64,7 @@ validate_int() { fi } -#----------------------------------------------------------------------------------------------- -# Require variable -#----------------------------------------------------------------------------------------------- +# Require variable to be set require_var() { local var="$1" if [[ -z "${!var:-}" ]]; then @@ -88,9 +73,7 @@ require_var() { fi } -#----------------------------------------------------------------------------------------------- -# Detect local/remote hosts and resolve Tailscale IPs -#----------------------------------------------------------------------------------------------- +# Detect local/remote host and SSH key detect_hosts() { LOCAL_HOSTNAME="$(hostname)" if [[ "$LOCAL_HOSTNAME" == "$HOST1" ]]; then