From 798517baf56c36278ba6a0ce0c2e5052e1224f70 Mon Sep 17 00:00:00 2001 From: FailedProxy Date: Sat, 21 Mar 2026 18:33:29 +0000 Subject: [PATCH] Structure Changes --- Rsync/rsync.sh | 169 ++++++++++++++++++++++ Rsync/rsync_appdata-failover_arrs_data.sh | 11 +- 2 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 Rsync/rsync.sh diff --git a/Rsync/rsync.sh b/Rsync/rsync.sh new file mode 100644 index 0000000..95f6cce --- /dev/null +++ b/Rsync/rsync.sh @@ -0,0 +1,169 @@ +#!/bin/bash +set -e +# Detect script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Load Master.conf from Git repo +MASTER_CONF="$SCRIPT_DIR/../Master.conf" +if [ -f "$MASTER_CONF" ]; then + source "$MASTER_CONF" + echo "Loaded Master.conf from $MASTER_CONF" +else + echo "Error: Master.conf not found at $MASTER_CONF" + exit 1 +fi +# Input Arguments & Directory +DIRECTORY="$1" # Directory to sync +if [[ -z "$DIRECTORY" ]]; then + echo "Usage: $0 [--dry-run] [VAR=value ...]" + exit 1 +fi +DRY_RUN=false +# Handle optional dry-run +if [[ "$2" == "--dry-run" ]]; then + DRY_RUN=true + shift 1 +fi +# Handle optional variable overrides: VAR=value format +for ARG in "${@:2}"; do + if [[ "$ARG" == *=* ]]; then + VAR_NAME="${ARG%%=*}" + VAR_VALUE="${ARG#*=}" + # Only override if variable already exists + if declare -p "$VAR_NAME" &>/dev/null; then + eval "$VAR_NAME=\"$VAR_VALUE\"" + echo "Overriding $VAR_NAME -> $VAR_VALUE" + else + echo "Warning: Unknown variable $VAR_NAME, ignoring." + fi + fi +done + +#----------------------------------------------------------------------------------------------- +#----------------------------- User Variables, Please adjust as needed ------------------------- +#----------------------------------------------------------------------------------------------- +#---------------------------- These variables Over Ride The Master.conf ------------------------ +#----------------------------------------------------------------------------------------------- +CRITICAL_CONTAINER_NAMES=("Sonarr" "Lidarr" "Readarr" "Radarr" "Prowlarr" "Bazarr" "Pinchflat") +DELAYED_CONTAINERS=("") +EXCLUDE_DIRS=("") +#----------------------------------------------------------------------------------------------- +#---------------------------- These variables Over Ride The Master.conf ------------------------ +#----------------------------------------------------------------------------------------------- +#------------------------End Of User Variables, Please adjust Above as needed ------------------ +#----------------------------------------------------------------------------------------------- + +# 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" -gt "$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") + ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker stop $container" + 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..." + sleep "$CONTAINER_DELAY" + fi + ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker start $container" + done +} + +#------------------------- Main ------------------------- +main() { + echo "[$LOCAL_SERVER_NAME] Syncing $DIRECTORY → $REMOTE_SERVER:$DIRECTORY" + + for i in $(seq 1 "$RETRY_COUNT"); do + if check_server_online; then + break + fi + echo "Remote $REMOTE_SERVER_NAME down, retrying in $SLEEP seconds..." + sleep "$SLEEP" + done + + 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 + ) + + for ex in "${EXCLUDE_DIRS[@]}"; do + RSYNC_OPTS+=(--exclude="$ex") + 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 + 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 + fi + done + + start_containers + echo "[$LOCAL_SERVER_NAME] Sync complete." +} + +# Run +main \ No newline at end of file diff --git a/Rsync/rsync_appdata-failover_arrs_data.sh b/Rsync/rsync_appdata-failover_arrs_data.sh index 21a4ca5..5018eb0 100644 --- a/Rsync/rsync_appdata-failover_arrs_data.sh +++ b/Rsync/rsync_appdata-failover_arrs_data.sh @@ -11,11 +11,20 @@ else echo "Error: Master.conf not found at $MASTER_CONF" exit 1 fi +# Directory +DIRECTORY="$1" # The directory to sync, passed as argument + + +if [[ -z "$DIRECTORY" ]]; then + echo "Usage: $0 " + exit 1 +fi + +echo "[$LOCAL_SERVER_NAME] Syncing $DIRECTORY → $REMOTE_SERVER:$DIRECTORY" #----------------------------------------------------------------------------------------------- #----------------------------- User Variables, Please adjust as needed ------------------------- #----------------------------------------------------------------------------------------------- -DIRECTORY="/mnt/user/appdata-Failover/Arrs_Stack/" DRY_RUN=false CRITICAL_CONTAINER_NAMES=("Sonarr" "Lidarr" "Readarr" "Radarr" "Prowlarr" "Bazarr" "Pinchflat") DELAYED_CONTAINERS=("")