Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions backup_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ EXCLUDE_FILE_TMP=$(mktemp)

# --- Securely parse the unified configuration file ---
if [ -f "$CONFIG_FILE" ]; then
# Initialize an empty array for SSH options for robustness
SSH_OPTS_ARR=()
in_exclude_block=false
while IFS= read -r line; do
# Handle the rsync exclusion block
Expand All @@ -50,11 +48,6 @@ if [ -f "$CONFIG_FILE" ]; then

# CRITICAL: Assign value as a literal string to prevent code injection
declare "$key"="$value"

# Robustly handle SSH options by converting the string to an array
if [[ "$key" == "SSH_OPTS_STR" ]]; then
read -r -a SSH_OPTS_ARR <<< "$value"
fi
fi
done < "$CONFIG_FILE"
else
Expand All @@ -71,7 +64,7 @@ MAX_LOG_SIZE=10485760 # 10 MB in bytes
RSYNC_BASE_OPTS=(
-a -z --delete --partial --timeout=60
--exclude-from="$EXCLUDE_FILE_TMP"
-e "ssh ${SSH_OPTS_ARR[@]}"
-e "ssh ${SSH_OPTS_STR:-}"
)

# =================================================================
Expand Down Expand Up @@ -114,7 +107,7 @@ send_notification() {
}

run_integrity_check() {
local rsync_check_opts=(-ainc -c --delete --exclude-from="$EXCLUDE_FILE_TMP" --out-format="%n" -e "ssh ${SSH_OPTS_ARR[@]}")
local rsync_check_opts=(-ainc -c --delete --exclude-from="$EXCLUDE_FILE_TMP" --out-format="%n" -e "ssh ${SSH_OPTS_STR:-}")
LC_ALL=C rsync "${rsync_check_opts[@]}" "$LOCAL_DIR" "$REMOTE_TARGET" 2>> "${LOG_FILE:-/dev/null}"
}

Expand All @@ -125,12 +118,10 @@ format_backup_stats() {
local files_created=""
local files_deleted=""

# First, try parsing the machine-readable format from --info=stats2
bytes_transferred=$(echo "$rsync_output" | grep 'Total_transferred_size:' | awk '{print $2}')
files_created=$(echo "$rsync_output" | grep 'Number_of_created_files:' | awk '{print $2}')
files_deleted=$(echo "$rsync_output" | grep 'Number_of_deleted_files:' | awk '{print $2}')

# If parsing failed, fall back to the human-readable --stats format
if [[ -z "$bytes_transferred" && -z "$files_created" && -z "$files_deleted" ]]; then
bytes_transferred=$(echo "$rsync_output" | grep 'Total transferred file size:' | awk '{gsub(/,/, ""); print $5}')
files_created=$(echo "$rsync_output" | grep 'Number of created files:' | awk '{print $5}')
Expand Down Expand Up @@ -165,7 +156,7 @@ for cmd in "${REQUIRED_CMDS[@]}"; do
fi
done

if ! ssh "${SSH_OPTS_ARR[@]}" -o BatchMode=yes -o ConnectTimeout=10 "$HETZNER_BOX" 'exit' 2>/dev/null; then
if ! ssh ${SSH_OPTS_STR:-} -o BatchMode=yes -o ConnectTimeout=10 "$HETZNER_BOX" 'exit' 2>/dev/null; then
send_notification "❌ SSH FAILED: ${HOSTNAME}" "x" "high" "failure" "Unable to SSH into $HETZNER_BOX. Check keys and connectivity."
trap - ERR; exit 6
fi
Expand Down