diff --git a/Rsync/rsync.sh b/Rsync/rsync.sh index d518019..717498c 100644 --- a/Rsync/rsync.sh +++ b/Rsync/rsync.sh @@ -23,32 +23,24 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../Master.conf" source "$SCRIPT_DIR/../common.sh" -parse_args "$@" - -# ---------------------------- -# INPUT HANDLING (FIXED) -# ---------------------------- - +# ----------------------------- ARG PARSING FIX ----------------------------- DIRECTORY="" +RAW_ARGS=() for ARG in "$@"; do case "$ARG" in --*|*=*) - # skip flags and key=value + RAW_ARGS+=("$ARG") ;; *) - if [[ -z "$DIRECTORY" ]]; then - DIRECTORY="$ARG" - fi + [[ -z "$DIRECTORY" ]] && DIRECTORY="$ARG" || RAW_ARGS+=("$ARG") ;; esac done -if [[ -z "$DIRECTORY" ]]; then - error "Missing directory" - echo "Usage: $0 [--dry-run] [--status] [VAR=value]" - exit 1 -fi +parse_args "${RAW_ARGS[@]}" + +[[ -z "$DIRECTORY" ]] && error "Missing directory" && exit 1 # ----------------------------- HOST ----------------------------- detect_hosts @@ -66,8 +58,8 @@ RETRY_COUNT=${PROFILE_RETRY_COUNT[$PROFILE_NAME]:-$RETRY_COUNT} SLEEP=${PROFILE_SLEEP[$PROFILE_NAME]:-$SLEEP} EXCLUDE_DIRS=(${PROFILE_EXCLUDE_DIRS[$PROFILE_NAME]:-${EXCLUDE_DIRS[@]}}) -# ----------------------------- STATUS MODE ----------------------------- -if [[ "$SHOW_STATUS" == true ]]; then +# ----------------------------- STATUS ----------------------------- +if [[ "${SHOW_STATUS:-false}" == true ]]; then show_status exit 0 fi @@ -75,20 +67,38 @@ fi # ----------------------------- HEADER ----------------------------- echo echo "$ICON_RUN Sync Starting" -echo "--------------------------------------------" -echo "Source: $DIRECTORY" -echo "Destination: $REMOTE_SERVER:$DIRECTORY" -echo "Profile: $PROFILE_NAME" -echo "Dry Run: $DRY_RUN" -echo "--------------------------------------------" +echo "Source: $DIRECTORY" +echo "Remote: $REMOTE_SERVER:$DIRECTORY" +echo "Profile: $PROFILE_NAME" +echo "Dry Run: $DRY_RUN" + +# ----------------------------- REMOTE CHECK FIX ----------------------------- +echo "$ICON_GEAR Checking remote..." + +REMOTE_OK=false + +for i in $(seq 1 "$RETRY_COUNT"); do + if ping -c 1 "$REMOTE_SERVER" &>/dev/null; then + success "Remote reachable" + REMOTE_OK=true + break + fi + warn "Retry $i/$RETRY_COUNT" + sleep "$SLEEP" +done + +if [[ "$REMOTE_OK" != true ]]; then + error "Remote unreachable" + exit 1 +fi # ----------------------------- RSYNC LIMIT ----------------------------- wait_for_rsync() { for i in $(seq 1 "$RETRY_COUNT"); do - RSYNC_COUNT=$(pgrep -fc "rsync.*root@${REMOTE_SERVER}" || true) + COUNT=$(pgrep -fc "rsync.*root@${REMOTE_SERVER}" || true) - if [[ "$RSYNC_COUNT" -ge "$MAX_RSYNC_PROCS" ]]; then - warn "Waiting for rsync slot ($RSYNC_COUNT)" + if [[ "$COUNT" -ge "$MAX_RSYNC_PROCS" ]]; then + warn "Waiting rsync slot ($COUNT)" sleep "$SLEEP" else return 0 @@ -96,75 +106,47 @@ wait_for_rsync() { done error "Too many rsync processes" + exit 1 } -# ----------------------------- SUMMARY ----------------------------- -print_summary() { - echo - echo "================ SUMMARY ================" - echo "Directory: $DIRECTORY" - echo "Profile: $PROFILE_NAME" - echo "Remote: $REMOTE_SERVER" - echo "Duration: ${DURATION:-unknown}s" - echo "Status: $1" - echo "Dry Run: $DRY_RUN" - echo "========================================" -} +wait_for_rsync -# ----------------------------- MAIN ----------------------------- -main() { +# ----------------------------- RUN ----------------------------- +log "Stopping containers" +stop_containers - echo "$ICON_GEAR Checking remote..." - for i in $(seq 1 "$RETRY_COUNT"); do - if ping -c 1 "$REMOTE_SERVER" &>/dev/null; then - success "Remote reachable" - break - fi - warn "Retrying ($i/$RETRY_COUNT)" +get_rsync_opts + +for ex in "${EXCLUDE_DIRS[@]}"; do + RSYNC_OPTS+=(--exclude="$ex") +done + +[[ "$DRY_RUN" == true ]] && RSYNC_OPTS+=("--dry-run") + +echo "$ICON_RUN Running rsync..." + +START=$(date +%s) + +for i in $(seq 1 "$RETRY_COUNT"); do + if rsync "${RSYNC_OPTS[@]}" \ + -e "ssh -i $SSH_KEY -T -o Compression=no -o IPQoS=throughput" \ + "$DIRECTORY" "root@${REMOTE_SERVER}:$DIRECTORY"; then + + success "Rsync complete" + break + else + warn "Rsync failed ($i/$RETRY_COUNT)" sleep "$SLEEP" - done + fi +done - [[ ! $(ping -c 1 "$REMOTE_SERVER" &>/dev/null) ]] && error "Remote unreachable" +start_containers - wait_for_rsync - - echo "$ICON_STOP Stopping containers..." - stop_containers - - echo "$ICON_GEAR Building rsync opts..." - get_rsync_opts - - for ex in "${EXCLUDE_DIRS[@]}"; do - RSYNC_OPTS+=(--exclude="$ex") - done - - [[ "$DRY_RUN" == true ]] && RSYNC_OPTS+=("--dry-run") - - echo "$ICON_RUN Running rsync..." - - START=$(date +%s) - - for i in $(seq 1 "$RETRY_COUNT"); do - if rsync "${RSYNC_OPTS[@]}" \ - -e "ssh -i $SSH_KEY -T -o Compression=no -o IPQoS=throughput" \ - "$DIRECTORY" "root@${REMOTE_SERVER}:$DIRECTORY"; then - - success "Rsync complete" - break - else - warn "Rsync failed" - - [[ $i -lt $RETRY_COUNT ]] && sleep "$SLEEP" - fi - done - - echo "$ICON_SYNC Restarting containers..." - start_containers - - END=$(date +%s) - DURATION=$((END - START)) - - print_summary "SUCCESS" -} - -main \ No newline at end of file +END=$(date +%s) +echo +echo "===== SUMMARY =====" +echo "Directory: $DIRECTORY" +echo "Profile: $PROFILE_NAME" +echo "Duration: $((END-START))s" +echo "Status: DONE" +echo "===================" \ No newline at end of file diff --git a/common.sh b/common.sh index 4a3be37..30c58d7 100644 --- a/common.sh +++ b/common.sh @@ -15,30 +15,21 @@ ICON_SYNC="🔄" ICON_GEAR="⚙️" # ----------------------------- Output Helpers ----------------------------- -info() { - echo "$ICON_INFO [INFO] $*" -} - -warn() { - echo "$ICON_WARN [WARN] $*" -} - -error() { - echo "$ICON_ERROR [ERROR] $*" -} - -success() { - echo "$ICON_SUCCESS [OK] $*" -} +info() { echo "$ICON_INFO [INFO] $*"; } +warn() { echo "$ICON_WARN [WARN] $*"; } +error() { echo "$ICON_ERROR [ERROR] $*"; } +success() { echo "$ICON_SUCCESS [OK] $*"; } log() { - [[ "$ENABLE_LOGGING" == true ]] && echo "[LOG] $*" + [[ "${ENABLE_LOGGING:-false}" == true ]] && echo "[LOG] $*" } # ----------------------------- Argument Parsing ----------------------------- parse_args() { - DRY_RUN=${DRY_RUN:-false} ENABLE_LOGGING=${ENABLE_LOGGING:-false} + DRY_RUN=${DRY_RUN:-false} + + local CLEAN_ARGS=() for ARG in "$@"; do if [[ "$ARG" == *=* ]]; then @@ -47,21 +38,15 @@ parse_args() { case "$VAR_NAME" in LOG) - if [[ "$VAR_VALUE" == "true" ]]; then - ENABLE_LOGGING=true - info "Verbose logging enabled" - elif [[ "$VAR_VALUE" == "false" ]]; then - ENABLE_LOGGING=false - else - warn "Invalid LOG value: $VAR_VALUE" - fi + [[ "$VAR_VALUE" == "true" ]] && ENABLE_LOGGING=true + [[ "$VAR_VALUE" == "false" ]] && ENABLE_LOGGING=false ;; *) if declare -p "$VAR_NAME" &>/dev/null; then printf -v "$VAR_NAME" '%s' "$VAR_VALUE" - log "Overriding $VAR_NAME -> $VAR_VALUE" + log "Set $VAR_NAME=$VAR_VALUE" else - warn "Unknown variable $VAR_NAME" + warn "Unknown variable: $VAR_NAME" fi ;; esac @@ -70,11 +55,9 @@ parse_args() { case "$ARG" in --dry-run|-n) DRY_RUN=true - info "Dry-run enabled" ;; --log) ENABLE_LOGGING=true - info "Logging enabled" ;; --no-log) ENABLE_LOGGING=false @@ -83,31 +66,29 @@ parse_args() { SHOW_STATUS=true ;; --help|-h) - echo "Usage: script [--dry-run|-n] [--log] [VAR=value ...]" + echo "Usage: script [--dry-run] [--log] [VAR=value]" exit 0 ;; *) - warn "Unknown argument: $ARG" + CLEAN_ARGS+=("$ARG") ;; esac fi done + + PARSED_ARGS=("${CLEAN_ARGS[@]}") } # ----------------------------- Validation ----------------------------- require_var() { - local var="$1" - [[ -z "${!var:-}" ]] && error "Missing required variable: $var" && exit 1 + [[ -z "${!1:-}" ]] && error "Missing required: $1" && exit 1 } validate_int() { - local name="$1" - local value="$2" - - [[ ! "${value:-}" =~ ^[0-9]+$ ]] && error "$name must be integer" && exit 1 + [[ ! "${2:-}" =~ ^[0-9]+$ ]] && error "$1 must be integer" && exit 1 } -# ----------------------------- HOST DETECTION ----------------------------- +# ----------------------------- Host Detection ----------------------------- detect_hosts() { LOCAL_HOSTNAME="$(hostname)" @@ -119,6 +100,7 @@ detect_hosts() { REMOTE_SERVER_NAME="$HOST1" else error "Unknown host: $LOCAL_HOSTNAME" + exit 1 fi declare -A SSH_KEYS @@ -127,24 +109,22 @@ detect_hosts() { SSH_KEY="${SSH_KEYS[$LOCAL_SERVER_NAME|$REMOTE_SERVER_NAME]}" - [[ -z "$SSH_KEY" ]] && error "Missing SSH key mapping" + [[ -z "$SSH_KEY" ]] && error "Missing SSH key mapping" && exit 1 + info "Host: $LOCAL_SERVER_NAME → $REMOTE_SERVER_NAME" } -# ----------------------------- REMOTE ----------------------------- +# ----------------------------- Remote ----------------------------- 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 remote IP" + [[ -z "$REMOTE_SERVER" ]] && error "Failed to resolve remote IP" && exit 1 + info "Remote IP: $REMOTE_SERVER" } -check_remote_online() { - ping -c 1 "$REMOTE_SERVER" &>/dev/null -} - -# ----------------------------- CONTAINERS ----------------------------- +# ----------------------------- Containers ----------------------------- declare -a RUNNING_CONTAINERS=() stop_containers() { @@ -176,27 +156,23 @@ start_containers() { done } -# ----------------------------- RSYNC ----------------------------- +# ----------------------------- RSYNC OPTIONS ----------------------------- get_rsync_opts() { if [[ -n "${PROFILE_RSYNC_OPTS[$PROFILE_NAME]:-}" ]]; then read -r -a RSYNC_OPTS <<< "${PROFILE_RSYNC_OPTS[$PROFILE_NAME]}" - log "Profile rsync opts loaded" else RSYNC_OPTS=("${DEFAULT_RSYNC_OPTS[@]}") - log "Default rsync opts loaded" fi } # ----------------------------- STATUS ----------------------------- show_status() { - echo - echo "================= STATUS =================" - echo "Local: $LOCAL_SERVER_NAME" - echo "Remote: $REMOTE_SERVER_NAME" - echo "IP: $REMOTE_SERVER" - echo "Profile: $PROFILE_NAME" - echo "Dry Run: $DRY_RUN" - echo "Logging: $ENABLE_LOGGING" - echo "Containers:${CRITICAL_CONTAINER_NAMES[*]:-(none)}" - echo "=========================================" + echo "===== STATUS =====" + echo "Local: $LOCAL_SERVER_NAME" + echo "Remote: $REMOTE_SERVER_NAME" + echo "IP: $REMOTE_SERVER" + echo "Profile: $PROFILE_NAME" + echo "DryRun: $DRY_RUN" + echo "Logging: $ENABLE_LOGGING" + echo "==================" } \ No newline at end of file