Files
Varaverk/Rsync/rsync.sh
T
2026-03-27 16:50:20 +00:00

214 lines
6.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
set -e
# ----------------------------------------------------------------------------------------------
# --------------------------------- Rsync Core Script ------------------------------------------
# ----------------------------------------------------------------------------------------------
# ---------------- User Variables, Please adjust in Master.conf as needed ----------------------
# ----------------------------------------------------------------------------------------------
#
# User variables can be adjusted in Master.conf
#
# Scripts now just contain runtime logic
#
# This new setup allows for profiles and arguments to use the core script
#
# Use arguments in unRAID User Plugin for directory
# Example = /mnt/user/appdata/unraid_scripts/Rsync/rsync.sh --dry-run
# ----------------------------------------------------------------------------------------------
# -------------- End Of User Variables, Please adjust in Master.conf as needed -----------------
# ----------------------------------------------------------------------------------------------
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Core System
source "$SCRIPT_DIR/../Master.conf"
source "$SCRIPT_DIR/../common.sh"
parse_args "$@"
# Input
if [[ -z "$DIRECTORY" ]]; then
echo "Usage: $0 <directory-to-sync> [--dry-run] [--status] [VAR=value ...]"
exit 1
fi
shift
# Host
detect_hosts
resolve_remote
# Profile
PROFILE_NAME=$(basename "$DIRECTORY" | tr '[:upper:]' '[:lower:]')
log "️ Detected profile: $PROFILE_NAME"
# Safe array normalization
normalize_list() {
local input="$1"
[[ -z "$input" ]] && return
read -r -a __out <<< "$input"
echo "${__out[@]}"
}
CRITICAL_CONTAINER_NAMES=($(normalize_list "${PROFILE_CRITICAL_CONTAINER_NAMES[$PROFILE_NAME]}"))
DELAYED_CONTAINERS=($(normalize_list "${PROFILE_DELAYED_CONTAINERS[$PROFILE_NAME]}"))
EXCLUDE_DIRS=($(normalize_list "${PROFILE_EXCLUDE_DIRS[$PROFILE_NAME]}"))
# Profile overrides
MAX_RSYNC_PROCS=${PROFILE_MAX_PROCS[$PROFILE_NAME]:-$MAX_RSYNC_PROCS}
BW_LIMIT=${PROFILE_BW_LIMIT[$PROFILE_NAME]:-$BW_LIMIT}
RETRY_COUNT=${PROFILE_RETRY_COUNT[$PROFILE_NAME]:-$RETRY_COUNT}
SLEEP=${PROFILE_SLEEP[$PROFILE_NAME]:-$SLEEP}
CONTAINER_DELAY=${PROFILE_CONTAINER_DELAY[$PROFILE_NAME]:-$CONTAINER_DELAY}
# Status Mode
if [[ "$SHOW_STATUS" == true ]]; then
echo "=================================================="
echo " ️ RSYNC STATUS"
echo "--------------------------------------------------"
echo " 📁 Source: $DIRECTORY"
echo " 🌐 Remote: $REMOTE_SERVER"
echo " 🧩 Profile: $PROFILE_NAME"
echo " 🚦 BW_LIMIT: $BW_LIMIT"
echo " 🔁 Max Procs: $MAX_RSYNC_PROCS"
echo " 🔁 Retries: $RETRY_COUNT"
echo " 🧪 Dry Run: $DRY_RUN"
echo " 📦 Containers: ${CRITICAL_CONTAINER_NAMES[*]}"
echo " 🚫 Excludes: ${EXCLUDE_DIRS[*]}"
echo "=================================================="
exit 0
fi
# Header
echo
echo "============================================================"
echo " 🚀 SYNC STARTING"
echo "------------------------------------------------------------"
echo " 📁 Source: $DIRECTORY"
echo " 🌐 Destination: $REMOTE_SERVER:$DIRECTORY"
echo " 🧩 Profile: $PROFILE_NAME"
echo " 🧪 Dry Run: $DRY_RUN"
echo "============================================================"
log "️ MAX_RSYNC_PROCS=$MAX_RSYNC_PROCS BW_LIMIT=$BW_LIMIT"
log "️ Containers: ${CRITICAL_CONTAINER_NAMES[*]}"
log "️ Excludes: ${EXCLUDE_DIRS[*]}"
# RSYNC SLOT CONTROL
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
warn "🟡 Waiting for rsync slot ($RSYNC_COUNT active)"
sleep "$SLEEP"
else
return 0
fi
done
error "🔴 Too many rsync processes running"
}
# MAIN
main() {
info "️ Checking remote connectivity..."
for i in $(seq 1 "$RETRY_COUNT"); do
if ping -c 1 "$REMOTE_SERVER" &>/dev/null; then
info "🟢 Remote reachable"
break
fi
warn "🟡 Remote unreachable (attempt $i/$RETRY_COUNT)"
sleep "$SLEEP"
done
if ! ping -c 1 "$REMOTE_SERVER" &>/dev/null; then
error "🔴 Remote server unreachable"
fi
wait_for_rsync
info "🟡 Stopping containers on remote..."
stop_containers
# Build RSYNC OPTIONS
get_rsync_opts
for ex in "${EXCLUDE_DIRS[@]}"; do
RSYNC_OPTS+=(--exclude="$ex")
done
if [[ "$DRY_RUN" == true ]]; then
RSYNC_OPTS+=(--dry-run)
info "🧪 Dry-run enabled"
fi
log "️ Final rsync opts: ${RSYNC_OPTS[*]}"
# EXECUTION
info "🚀 Starting rsync..."
START_TIME=$(date +%s)
for attempt in $(seq 1 "$RETRY_COUNT"); do
info "️ 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
info "🟢 Rsync completed successfully"
break
else
warn "❌ Rsync failed"
if [[ "$attempt" -lt "$RETRY_COUNT" ]]; then
warn "🟡 Retrying in $SLEEP seconds..."
sleep "$SLEEP"
else
error "🔴 All rsync attempts failed"
start_containers
fi
fi
done
# FINALIZE
info "🟡 Restarting containers..."
start_containers
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
# SUMMARY
echo "============================================================"
if [[ "${PIPESTATUS[0]}" -eq 0 ]]; then
echo " 🟢 SYNC SUMMARY"
echo "------------------------------------------------------------"
echo " 📁 Directory: $DIRECTORY"
echo " 🧩 Profile: $PROFILE_NAME"
echo " 🌐 Remote: $REMOTE_SERVER"
echo " ⏱ Duration: ${DURATION}s"
echo " 📡 Status: 🟢 SUCCESS"
echo " 🧪 Dry Run: $DRY_RUN"
else
echo " 🔴 SYNC SUMMARY"
echo "------------------------------------------------------------"
echo " 📁 Directory: $DIRECTORY"
echo " 🧩 Profile: $PROFILE_NAME"
echo " 🌐 Remote: $REMOTE_SERVER"
echo " ⏱ Duration: ${DURATION}s"
echo " 📡 Status: 🔴 FAILED"
echo " 🧪 Dry Run: $DRY_RUN"
fi
echo "============================================================"
info "️ Sync complete"
}
main