2
2
3
3
# =================================================================
4
4
# SCRIPT INITIALIZATION & SETUP
5
- # v0.11 - 2025.08.09
5
+ # v0.12 - 2025.08.10
6
6
# =================================================================
7
7
set -Euo pipefail
8
8
umask 077
@@ -112,9 +112,12 @@ run_integrity_check() {
112
112
local rsync_check_opts=(-ainc -c --delete --exclude-from=" $EXCLUDE_FILE_TMP " --out-format=" %n" -e " ssh ${SSH_OPTS_STR:- } " )
113
113
114
114
for dir in $BACKUP_DIRS ; do
115
- local remote_subdir=" ${REMOTE_TARGET} /$( basename " $dir " ) /"
115
+ local remote_path=" ${REMOTE_TARGET}${dir#/ } "
116
+
117
+ echo " --- Integrity Check: $dir ---" >&2
118
+
116
119
# shellcheck disable=SC2086
117
- LC_ALL=C rsync " ${rsync_check_opts[@]} " " $dir " " $remote_subdir " 2>> " ${LOG_FILE:-/ dev/ null} "
120
+ LC_ALL=C rsync " ${rsync_check_opts[@]} " " $dir " " $remote_path " 2>> " ${LOG_FILE:-/ dev/ null} "
118
121
done
119
122
}
120
123
@@ -135,7 +138,6 @@ format_backup_stats() {
135
138
local files_created=$( parse_stat " $rsync_output " ' Number_of_created_files:' ' {s+=$2} END {print s}' )
136
139
local files_deleted=$( parse_stat " $rsync_output " ' Number_of_deleted_files:' ' {s+=$2} END {print s}' )
137
140
138
- # Fallback for older rsync versions
139
141
if [[ -z " $bytes_transferred " && -z " $files_created " && -z " $files_deleted " ]]; then
140
142
bytes_transferred=$( parse_stat " $rsync_output " ' Total transferred file size:' ' {gsub(/,/, ""); s+=$5} END {print s}' )
141
143
files_created=$( parse_stat " $rsync_output " ' Number of created files:' ' {s+=$5} END {print s}' )
@@ -202,10 +204,10 @@ if [[ "${1:-}" ]]; then
202
204
echo " --- DRY RUN MODE ACTIVATED ---"
203
205
DRY_RUN_FAILED=false
204
206
for dir in $BACKUP_DIRS ; do
205
- remote_subdir =" ${REMOTE_TARGET} / $( basename " $ dir" ) / "
206
- echo " --- Checking dry run for: $dir -> $remote_subdir "
207
+ remote_path =" ${REMOTE_TARGET}${ dir#/ } "
208
+ echo " --- Checking dry run for: $dir -> $remote_path "
207
209
# shellcheck disable=SC2086
208
- if ! rsync " ${RSYNC_BASE_OPTS[@]} " --dry-run --info=progress2 " $dir " " $remote_subdir " ; then
210
+ if ! rsync " ${RSYNC_BASE_OPTS[@]} " --dry-run --info=progress2 " $dir " " $remote_path " ; then
209
211
DRY_RUN_FAILED=true
210
212
fi
211
213
done
@@ -220,23 +222,28 @@ if [[ "${1:-}" ]]; then
220
222
--checksum | --summary)
221
223
echo " --- INTEGRITY CHECK MODE ACTIVATED ---"
222
224
echo " Calculating differences..."
225
+ START_TIME_INTEGRITY=$( date +%s)
223
226
FILE_DISCREPANCIES=$( run_integrity_check)
227
+ END_TIME_INTEGRITY=$( date +%s)
228
+ DURATION_INTEGRITY=$(( END_TIME_INTEGRITY - START_TIME_INTEGRITY))
229
+
230
+ CLEAN_DISCREPANCIES=$( echo " $FILE_DISCREPANCIES " | grep -v ' ^\*' )
224
231
225
232
if [[ " $1 " == " --summary" ]]; then
226
- MISMATCH_COUNT=$( echo " $FILE_DISCREPANCIES " | wc -l)
233
+ MISMATCH_COUNT=$( echo " $CLEAN_DISCREPANCIES " | wc -l)
227
234
printf " 🚨 Total files with checksum mismatches: %d\n" " $MISMATCH_COUNT "
228
235
log_message " Summary mode check found $MISMATCH_COUNT mismatched files."
229
236
send_notification " 📊 Backup Summary: ${HOSTNAME} " " bar_chart" " ${NTFY_PRIORITY_SUCCESS} " " success" " Mismatched files found: $MISMATCH_COUNT "
230
237
else # --checksum
231
- if [ -z " $FILE_DISCREPANCIES " ]; then
238
+ if [ -z " $CLEAN_DISCREPANCIES " ]; then
232
239
echo " ✅ Checksum validation passed. No discrepancies found."
233
240
log_message " Checksum validation passed. No discrepancies found."
234
241
send_notification " ✅ Backup Integrity OK: ${HOSTNAME} " " white_check_mark" " ${NTFY_PRIORITY_SUCCESS} " " success" " Checksum validation passed. No discrepancies found."
235
242
else
236
243
log_message " Backup integrity check FAILED. Found discrepancies."
237
- ISSUE_LIST=$( echo " ${FILE_DISCREPANCIES} " | head -n 10)
238
- printf " ❌ Backup integrity check FAILED. First 10 differing files:\n%s\n" " ${ISSUE_LIST} "
239
- printf -v FAILURE_MSG " Backup integrity check FAILED.\n\nFirst 10 differing files:\n %s\n\nCheck log for full details. " " ${ISSUE_LIST} "
244
+ ISSUE_LIST=$( echo " $CLEAN_DISCREPANCIES " | head -n 10)
245
+ 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 ))
246
+ printf " ❌ %s\n" " $FAILURE_MSG "
240
247
send_notification " ❌ Backup Integrity FAILED: ${HOSTNAME} " " x" " ${NTFY_PRIORITY_FAILURE} " " failure" " ${FAILURE_MSG} "
241
248
fi
242
249
fi
@@ -266,7 +273,7 @@ full_rsync_output=""
266
273
for dir in $BACKUP_DIRS ; do
267
274
log_message " Backing up directory: $dir "
268
275
269
- remote_subdir =" ${REMOTE_TARGET} / $( basename " $ dir" ) / "
276
+ remote_path =" ${REMOTE_TARGET}${ dir#/ } "
270
277
271
278
RSYNC_LOG_TMP=$( mktemp)
272
279
RSYNC_EXIT_CODE=0
@@ -275,12 +282,12 @@ for dir in $BACKUP_DIRS; do
275
282
if [[ " $VERBOSE_MODE " == " true" ]]; then
276
283
RSYNC_OPTS+=(--info=stats2,progress2)
277
284
# shellcheck disable=SC2086
278
- nice -n 19 ionice -c 3 rsync " ${RSYNC_OPTS[@]} " " $dir " " $remote_subdir " 2>&1 | tee " $RSYNC_LOG_TMP "
285
+ nice -n 19 ionice -c 3 rsync " ${RSYNC_OPTS[@]} " " $dir " " $remote_path " 2>&1 | tee " $RSYNC_LOG_TMP "
279
286
RSYNC_EXIT_CODE=${PIPESTATUS[0]}
280
287
else
281
288
RSYNC_OPTS+=(--info=stats2)
282
289
# shellcheck disable=SC2086
283
- nice -n 19 ionice -c 3 rsync " ${RSYNC_OPTS[@]} " " $dir " " $remote_subdir " > " $RSYNC_LOG_TMP " 2>&1 || RSYNC_EXIT_CODE=$?
290
+ nice -n 19 ionice -c 3 rsync " ${RSYNC_OPTS[@]} " " $dir " " $remote_path " > " $RSYNC_LOG_TMP " 2>&1 || RSYNC_EXIT_CODE=$?
284
291
fi
285
292
286
293
cat " $RSYNC_LOG_TMP " >> " $LOG_FILE "
0 commit comments