@@ -222,7 +222,7 @@ END_EXCLUDES
222
222
223
223
# =================================================================
224
224
# SCRIPT INITIALIZATION & SETUP
225
- # v0.11 - 2025.08.09
225
+ # v0.12 - 2025.08.10
226
226
# =================================================================
227
227
set -Euo pipefail
228
228
umask 077
@@ -332,9 +332,12 @@ run_integrity_check() {
332
332
local rsync_check_opts=(-ainc -c --delete --exclude-from=" $EXCLUDE_FILE_TMP " --out-format=" %n" -e " ssh ${SSH_OPTS_STR:- } " )
333
333
334
334
for dir in $BACKUP_DIRS ; do
335
- local remote_subdir=" ${REMOTE_TARGET} /$( basename " $dir " ) /"
335
+ local remote_path=" ${REMOTE_TARGET}${dir#/ } "
336
+
337
+ echo " --- Integrity Check: $dir ---" >&2
338
+
336
339
# shellcheck disable=SC2086
337
- LC_ALL=C rsync " ${rsync_check_opts[@]} " " $dir " " $remote_subdir " 2>> " ${LOG_FILE:-/ dev/ null} "
340
+ LC_ALL=C rsync " ${rsync_check_opts[@]} " " $dir " " $remote_path " 2>> " ${LOG_FILE:-/ dev/ null} "
338
341
done
339
342
}
340
343
@@ -355,7 +358,6 @@ format_backup_stats() {
355
358
local files_created=$( parse_stat " $rsync_output " ' Number_of_created_files:' ' {s+=$2} END {print s}' )
356
359
local files_deleted=$( parse_stat " $rsync_output " ' Number_of_deleted_files:' ' {s+=$2} END {print s}' )
357
360
358
- # Fallback for older rsync versions
359
361
if [[ -z " $bytes_transferred " && -z " $files_created " && -z " $files_deleted " ]]; then
360
362
bytes_transferred=$( parse_stat " $rsync_output " ' Total transferred file size:' ' {gsub(/,/, ""); s+=$5} END {print s}' )
361
363
files_created=$( parse_stat " $rsync_output " ' Number of created files:' ' {s+=$5} END {print s}' )
@@ -422,10 +424,10 @@ if [[ "${1:-}" ]]; then
422
424
echo " --- DRY RUN MODE ACTIVATED ---"
423
425
DRY_RUN_FAILED=false
424
426
for dir in $BACKUP_DIRS ; do
425
- remote_subdir =" ${REMOTE_TARGET} / $( basename " $ dir" ) / "
426
- echo " --- Checking dry run for: $dir -> $remote_subdir "
427
+ remote_path =" ${REMOTE_TARGET}${ dir#/ } "
428
+ echo " --- Checking dry run for: $dir -> $remote_path "
427
429
# shellcheck disable=SC2086
428
- if ! rsync " ${RSYNC_BASE_OPTS[@]} " --dry-run --info=progress2 " $dir " " $remote_subdir " ; then
430
+ if ! rsync " ${RSYNC_BASE_OPTS[@]} " --dry-run --info=progress2 " $dir " " $remote_path " ; then
429
431
DRY_RUN_FAILED=true
430
432
fi
431
433
done
@@ -440,23 +442,28 @@ if [[ "${1:-}" ]]; then
440
442
--checksum | --summary)
441
443
echo " --- INTEGRITY CHECK MODE ACTIVATED ---"
442
444
echo " Calculating differences..."
445
+ START_TIME_INTEGRITY=$( date +%s)
443
446
FILE_DISCREPANCIES=$( run_integrity_check)
447
+ END_TIME_INTEGRITY=$( date +%s)
448
+ DURATION_INTEGRITY=$(( END_TIME_INTEGRITY - START_TIME_INTEGRITY))
449
+
450
+ CLEAN_DISCREPANCIES=$( echo " $FILE_DISCREPANCIES " | grep -v ' ^\*' )
444
451
445
452
if [[ " $1 " == " --summary" ]]; then
446
- MISMATCH_COUNT=$( echo " $FILE_DISCREPANCIES " | wc -l)
453
+ MISMATCH_COUNT=$( echo " $CLEAN_DISCREPANCIES " | wc -l)
447
454
printf " 🚨 Total files with checksum mismatches: %d\n" " $MISMATCH_COUNT "
448
455
log_message " Summary mode check found $MISMATCH_COUNT mismatched files."
449
456
send_notification " 📊 Backup Summary: ${HOSTNAME} " " bar_chart" " ${NTFY_PRIORITY_SUCCESS} " " success" " Mismatched files found: $MISMATCH_COUNT "
450
457
else # --checksum
451
- if [ -z " $FILE_DISCREPANCIES " ]; then
458
+ if [ -z " $CLEAN_DISCREPANCIES " ]; then
452
459
echo " ✅ Checksum validation passed. No discrepancies found."
453
460
log_message " Checksum validation passed. No discrepancies found."
454
461
send_notification " ✅ Backup Integrity OK: ${HOSTNAME} " " white_check_mark" " ${NTFY_PRIORITY_SUCCESS} " " success" " Checksum validation passed. No discrepancies found."
455
462
else
456
463
log_message " Backup integrity check FAILED. Found discrepancies."
457
- ISSUE_LIST=$( echo " ${FILE_DISCREPANCIES} " | head -n 10)
458
- printf " ❌ Backup integrity check FAILED. First 10 differing files:\n%s\n" " ${ISSUE_LIST} "
459
- printf -v FAILURE_MSG " Backup integrity check FAILED.\n\nFirst 10 differing files:\n %s\n\nCheck log for full details. " " ${ISSUE_LIST} "
464
+ ISSUE_LIST=$( echo " $CLEAN_DISCREPANCIES " | head -n 10)
465
+ printf -v FAILURE_MSG " Backup integrity check FAILED.\n\nFirst 10 differing files:\n%s\n\nCheck duration: %dm %ds " " ${ISSUE_LIST} " $(( DURATION_INTEGRITY / 60 )) $(( DURATION_INTEGRITY % 60 ))
466
+ printf " ❌ %s\n" " $FAILURE_MSG "
460
467
send_notification " ❌ Backup Integrity FAILED: ${HOSTNAME} " " x" " ${NTFY_PRIORITY_FAILURE} " " failure" " ${FAILURE_MSG} "
461
468
fi
462
469
fi
@@ -486,7 +493,7 @@ full_rsync_output=""
486
493
for dir in $BACKUP_DIRS ; do
487
494
log_message " Backing up directory: $dir "
488
495
489
- remote_subdir =" ${REMOTE_TARGET} / $( basename " $ dir" ) / "
496
+ remote_path =" ${REMOTE_TARGET}${ dir#/ } "
490
497
491
498
RSYNC_LOG_TMP=$( mktemp)
492
499
RSYNC_EXIT_CODE=0
@@ -495,12 +502,12 @@ for dir in $BACKUP_DIRS; do
495
502
if [[ " $VERBOSE_MODE " == " true" ]]; then
496
503
RSYNC_OPTS+=(--info=stats2,progress2)
497
504
# shellcheck disable=SC2086
498
- nice -n 19 ionice -c 3 rsync " ${RSYNC_OPTS[@]} " " $dir " " $remote_subdir " 2>&1 | tee " $RSYNC_LOG_TMP "
505
+ nice -n 19 ionice -c 3 rsync " ${RSYNC_OPTS[@]} " " $dir " " $remote_path " 2>&1 | tee " $RSYNC_LOG_TMP "
499
506
RSYNC_EXIT_CODE=${PIPESTATUS[0]}
500
507
else
501
508
RSYNC_OPTS+=(--info=stats2)
502
509
# shellcheck disable=SC2086
503
- nice -n 19 ionice -c 3 rsync " ${RSYNC_OPTS[@]} " " $dir " " $remote_subdir " > " $RSYNC_LOG_TMP " 2>&1 || RSYNC_EXIT_CODE=$?
510
+ nice -n 19 ionice -c 3 rsync " ${RSYNC_OPTS[@]} " " $dir " " $remote_path " > " $RSYNC_LOG_TMP " 2>&1 || RSYNC_EXIT_CODE=$?
504
511
fi
505
512
506
513
cat " $RSYNC_LOG_TMP " >> " $LOG_FILE "
0 commit comments