diff --git a/common.sh b/common.sh index 8ae87ab..a359180 100644 --- a/common.sh +++ b/common.sh @@ -20,65 +20,43 @@ error() { echo "$ICON_ERROR [ERROR] $*"; } success() { echo "$ICON_SUCCESS [OK] $*"; } log() { [[ "${ENABLE_LOGGING:-false}" == true ]] && echo "[LOG] $*"; } -# ----------------------------- LOAD MASTER CONFIG ----------------------------- -# MUST be defined before calling engine -# Example: -# source /boot/config/master.conf -if [[ -n "${MASTER_CONF_PATH:-}" ]]; then - source "$MASTER_CONF_PATH" -fi +# ----------------------------- LOAD MASTER CONF ----------------------------- +[[ -n "${MASTER_CONF_PATH:-}" ]] && source "$MASTER_CONF_PATH" # ----------------------------- ARG PARSING ----------------------------- parse_args() { ENABLE_LOGGING=${ENABLE_LOGGING:-false} DRY_RUN=${DRY_RUN:-false} - SHOW_STATUS=${SHOW_STATUS:-false} CLEAN_ARGS=() - for ARG in "$@"; do case "$ARG" in --dry-run|-n) DRY_RUN=true ;; --log) ENABLE_LOGGING=true ;; --no-log) ENABLE_LOGGING=false ;; - --status) SHOW_STATUS=true ;; *) CLEAN_ARGS+=("$ARG") ;; esac done - PARSED_ARGS=("${CLEAN_ARGS[@]}") } -# ----------------------------- HOST DETECTION ----------------------------- +# ----------------------------- HOST ----------------------------- detect_hosts() { LOCAL_HOSTNAME="$(hostname)" if [[ "$LOCAL_HOSTNAME" == "$HOST1" ]]; then LOCAL_SERVER_NAME="$HOST1" REMOTE_SERVER_NAME="$HOST2" - elif [[ "$LOCAL_HOSTNAME" == "$HOST2" ]]; then + else LOCAL_SERVER_NAME="$HOST2" REMOTE_SERVER_NAME="$HOST1" - else - error "Unknown host: $LOCAL_HOSTNAME" - exit 1 fi - declare -A SSH_KEYS - SSH_KEYS["$HOST1|$HOST2"]="$HOST1_SSH_KEY" - SSH_KEYS["$HOST2|$HOST1"]="$HOST2_SSH_KEY" - - SSH_KEY="${SSH_KEYS[$LOCAL_SERVER_NAME|$REMOTE_SERVER_NAME]}" - - [[ -z "$SSH_KEY" ]] && error "Missing SSH key mapping" && exit 1 - info "Host: $LOCAL_SERVER_NAME → $REMOTE_SERVER_NAME" } -# ----------------------------- REMOTE RESOLVE ----------------------------- resolve_remote_ip() { - REMOTE_SERVER=$(tailscale ip -4 "$REMOTE_SERVER_NAME" 2>/dev/null) - [[ -z "$REMOTE_SERVER" ]] && error "Failed to resolve remote IP" && exit 1 + REMOTE_SERVER=$(tailscale ip -4 "$REMOTE_SERVER_NAME") info "Remote IP: $REMOTE_SERVER" } @@ -86,72 +64,46 @@ resolve_remote_ip() { RUNNING_CONTAINERS=() stop_containers() { - [[ ${#CRITICAL_CONTAINER_NAMES[@]} -eq 0 ]] && return - info "Stopping containers..." RUNNING_CONTAINERS=() for c in "${CRITICAL_CONTAINER_NAMES[@]}"; do - - STATUS=$(ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" \ - "docker inspect -f '{{.State.Running}}' $c 2>/dev/null" || echo "false") + STATUS=$(ssh root@"$REMOTE_SERVER" "docker inspect -f '{{.State.Running}}' $c 2>/dev/null" || echo "false") if [[ "$STATUS" == "true" ]]; then warn "Stopping $c" RUNNING_CONTAINERS+=("$c") - if ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker stop $c" >/dev/null; then - success "$c stopped" - else - error "Failed to stop $c" - fi + ssh root@"$REMOTE_SERVER" "docker stop $c" >/dev/null && \ + success "$c stopped" || error "$c failed to stop" else - echo "$ICON_STOPPED $c already stopped" + echo "🟢 $c already stopped" fi done } start_containers() { - [[ ${#RUNNING_CONTAINERS[@]} -eq 0 ]] && return - info "Starting containers..." for c in "${RUNNING_CONTAINERS[@]}"; do info "Starting $c" - - if ssh -i "$SSH_KEY" root@"$REMOTE_SERVER" "docker start $c" >/dev/null; then - success "$c started" - else - error "Failed to start $c" - fi + ssh root@"$REMOTE_SERVER" "docker start $c" >/dev/null && \ + success "$c started" || error "$c failed to start" done } # ----------------------------- RSYNC LIMITER ----------------------------- wait_for_rsync() { - : "${RETRY_COUNT:=5}" - : "${MAX_RSYNC_PROCS:=2}" - : "${SLEEP:=2}" + COUNT=$(pgrep -x rsync | wc -l || true) - for _ in $(seq 1 "$RETRY_COUNT"); do + while [[ "$COUNT" -ge "${MAX_RSYNC_PROCS:-2}" ]]; do + warn "Waiting rsync slot..." + sleep 2 COUNT=$(pgrep -x rsync | wc -l || true) - - if [[ "$COUNT" -ge "$MAX_RSYNC_PROCS" ]]; then - warn "Waiting rsync slot ($COUNT/$MAX_RSYNC_PROCS)" - sleep "$SLEEP" - else - return 0 - fi done - - error "Too many rsync processes" - exit 1 } -# ----------------------------------------------------------------------------------------------- -# ----------------------------- DEFAULT RSYNC OPTIONS ------------------------------------------- -# ----------------------------------------------------------------------------------------------- - +# ----------------------------- RSYNC OPTIONS ----------------------------- DEFAULT_RSYNC_OPTS=( --archive --delete @@ -161,20 +113,10 @@ DEFAULT_RSYNC_OPTS=( --stats ) -# ----------------------------------------------------------------------------------------------- -# ----------------------------- PROFILE HANDLING (FROM MASTER.CONF) ----------------------------- -# ----------------------------------------------------------------------------------------------- - get_rsync_opts() { RSYNC_OPTS=("${DEFAULT_RSYNC_OPTS[@]}") - # Ensure profile map exists - if [[ -z "${PROFILE_BW_LIMIT[*]}" ]]; then - warn "PROFILE_BW_LIMIT missing from Master.conf - using unlimited" - declare -A PROFILE_BW_LIMIT - fi - BW_LIMIT="${PROFILE_BW_LIMIT[$PROFILE_NAME]:-0}" if [[ "$BW_LIMIT" -gt 0 ]]; then @@ -183,13 +125,9 @@ get_rsync_opts() { else log "bwlimit unlimited (profile: $PROFILE_NAME)" fi - - if [[ "${ENABLE_PROGRESS:-false}" == true ]]; then - log "Progress mode enabled" - fi } -# ----------------------------- RSYNC EXECUTION (FIXED OUTPUT) ----------------------------- +# ----------------------------- RSYNC EXECUTION (WITH METRICS) ----------------------------- run_rsync() { wait_for_rsync @@ -197,23 +135,38 @@ run_rsync() { echo "🚀 Running rsync..." - # IMPORTANT FIX: - # - no --quiet - # - no output suppression - # - direct execution for real-time streaming + RSYNC_START=$(date +%s) - rsync "${RSYNC_OPTS[@]}" \ + RSYNC_OUTPUT=$(rsync "${RSYNC_OPTS[@]}" \ "$SRC/" \ - "root@$REMOTE_SERVER:$DEST/" + "root@$REMOTE_SERVER:$DEST/") + + RSYNC_END=$(date +%s) + DURATION=$((RSYNC_END - RSYNC_START)) + + # ----------------------------- METRICS EXTRACTION ----------------------------- + TRANSFERRED=$(echo "$RSYNC_OUTPUT" | grep "Total transferred file size" | awk '{print $5}') + FILES_CHANGED=$(echo "$RSYNC_OUTPUT" | grep "Number of regular files transferred" | awk '{print $6}') + DELETED=$(echo "$RSYNC_OUTPUT" | grep "Number of deleted files" | awk '{print $5}') + AVG_SPEED=$(echo "$RSYNC_OUTPUT" | grep -Eo '[0-9.]+[ ]*bytes/sec' | tail -1) } -# ----------------------------- STATUS ----------------------------- -show_status() { - echo "===== SYNC STATUS =====" - echo "Local: $LOCAL_SERVER_NAME" - echo "Remote: $REMOTE_SERVER_NAME" - echo "IP: $REMOTE_SERVER" - echo "Profile: $PROFILE_NAME" - echo "Progress: ${ENABLE_PROGRESS:-false}" - echo "=======================" -} \ No newline at end of file +# ----------------------------- SUMMARY (SINGLE SOURCE OF TRUTH) ----------------------------- +show_summary() { + + echo "" + echo "===== SUMMARY =====" + echo "Directory: $SRC" + echo "Profile: $PROFILE_NAME" + echo "" + echo "Transferred: ${TRANSFERRED:-unknown}" + echo "Changed files: ${FILES_CHANGED:-0}" + echo "Deleted files: ${DELETED:-0}" + echo "" + echo "Duration: ${DURATION:-0}s" + echo "Avg speed: ${AVG_SPEED:-unknown}" + echo "" + echo "Status: DONE" + echo "===================" +} +🟢 WHAT IS \ No newline at end of file