@@ -222,11 +222,13 @@ END_EXCLUDES
222
222
223
223
# =================================================================
224
224
# SCRIPT INITIALIZATION & SETUP
225
- # v0.12 - 2025.08.10
225
+ # v0.13 - 2025.08.10
226
226
# =================================================================
227
227
set -Euo pipefail
228
228
umask 077
229
229
230
+ HOSTNAME=$( hostname -s)
231
+
230
232
# Check if the script is being run as root
231
233
if (( EUID != 0 )) ; then
232
234
echo " ❌ This script must be run as root or with sudo." >&2
@@ -251,7 +253,7 @@ if [ -f "$CONFIG_FILE" ]; then
251
253
fi
252
254
253
255
if $in_exclude_block ; then
254
- [[ ! " $line " =~ ^\s * # |^\s*$ ]] && echo "$line" >> "$EXCLUDE_FILE_TMP"
256
+ [[ ! " $line " =~ ^([[:space:]] * # |[[:space:]]*$) ]] && echo "$line" >> "$EXCLUDE_FILE_TMP"
255
257
continue
256
258
fi
257
259
@@ -383,34 +385,54 @@ cleanup() {
383
385
# PRE-FLIGHT CHECKS & SETUP
384
386
# =================================================================
385
387
388
+ run_preflight_checks () {
389
+ # This function runs all checks. If 'true' is passed as an argument,
390
+ # it runs in a verbose test mode instead of sending notifications.
391
+ local test_mode=${1:- false}
392
+ local check_failed=false
393
+
394
+ # 1. Check for required commands
395
+ if [[ " $test_mode " == " true" ]]; then echo " --- Checking required commands..." ; fi
396
+ for cmd in " ${REQUIRED_CMDS[@]} " ; do
397
+ if ! command -v " $cmd " & > /dev/null; then
398
+ echo " ❌ FATAL: Required command '$cmd ' not found. Please install it." >&2
399
+ check_failed=true
400
+ fi
401
+ done
402
+ if [[ " $check_failed " == " true" ]]; then exit 10; fi
403
+ if [[ " $test_mode " == " true" ]]; then echo " ✅ All required commands are present." ; fi
404
+
405
+ # 2. Check SSH connectivity
406
+ if [[ " $test_mode " == " true" ]]; then echo " --- Checking SSH connectivity..." ; fi
407
+ if ! ssh ${SSH_OPTS_STR:- } -o BatchMode=yes -o ConnectTimeout=10 " $HETZNER_BOX " ' exit' 2> /dev/null; then
408
+ local err_msg=" Unable to SSH into $HETZNER_BOX . Check keys and connectivity."
409
+ if [[ " $test_mode " == " true" ]]; then echo " ❌ $err_msg " ; else send_notification " ❌ SSH FAILED: ${HOSTNAME} " " x" " ${NTFY_PRIORITY_FAILURE} " " failure" " $err_msg " ; fi
410
+ exit 6
411
+ fi
412
+ if [[ " $test_mode " == " true" ]]; then echo " ✅ SSH connectivity OK." ; fi
413
+
414
+ # 3. Check backup directories
415
+ if [[ " $test_mode " == " true" ]]; then echo " --- Checking backup directories..." ; fi
416
+ for dir in $BACKUP_DIRS ; do
417
+ if [[ ! -d " $dir " ]] || [[ " $dir " != * / ]]; then
418
+ local err_msg=" A directory in BACKUP_DIRS ('$dir ') must exist and end with a trailing slash ('/')."
419
+ if [[ " $test_mode " == " true" ]]; then echo " ❌ FATAL: $err_msg " ; else send_notification " ❌ Backup FAILED: ${HOSTNAME} " " x" " ${NTFY_PRIORITY_FAILURE} " " failure" " FATAL: $err_msg " ; fi
420
+ exit 2
421
+ fi
422
+ done
423
+ if [[ " $test_mode " == " true" ]]; then echo " ✅ All backup directories are valid." ; fi
424
+ }
425
+
386
426
trap cleanup EXIT
387
427
trap ' send_notification "❌ Backup Crashed: ${HOSTNAME}" "x" "${NTFY_PRIORITY_FAILURE}" "failure" "Backup script terminated unexpectedly. Check log: ${LOG_FILE:-/dev/null}"' ERR
388
428
389
429
REQUIRED_CMDS=(rsync curl flock hostname date stat mv touch awk numfmt grep printf nice ionice sed mktemp basename)
390
- for cmd in " ${REQUIRED_CMDS[@]} " ; do
391
- if ! command -v " $cmd " & > /dev/null; then
392
- echo " FATAL: Required command '$cmd ' not found. Please install it." >&2 ; trap - ERR; exit 10
393
- fi
394
- done
395
-
396
- if ! ssh ${SSH_OPTS_STR:- } -o BatchMode=yes -o ConnectTimeout=10 " $HETZNER_BOX " ' exit' 2> /dev/null; then
397
- send_notification " ❌ SSH FAILED: ${HOSTNAME} " " x" " ${NTFY_PRIORITY_FAILURE} " " failure" " Unable to SSH into $HETZNER_BOX . Check keys and connectivity."
398
- trap - ERR; exit 6
399
- fi
400
-
401
- for dir in $BACKUP_DIRS ; do
402
- if [[ ! -d " $dir " ]] || [[ " $dir " != * / ]]; then
403
- send_notification " ❌ Backup FAILED: ${HOSTNAME} " " x" " ${NTFY_PRIORITY_FAILURE} " " failure" " FATAL: A directory in BACKUP_DIRS ('$dir ') must exist and end with a trailing slash ('/')."
404
- trap - ERR; exit 2
405
- fi
406
- done
407
430
408
431
409
432
# =================================================================
410
433
# SCRIPT EXECUTION
411
434
# =================================================================
412
435
413
- HOSTNAME= $( hostname -s)
414
436
VERBOSE_MODE=false
415
437
if [[ " ${1:- } " == " --verbose" ]]; then
416
438
VERBOSE_MODE=true; shift
@@ -468,6 +490,14 @@ if [[ "${1:-}" ]]; then
468
490
fi
469
491
fi
470
492
exit 0 ;;
493
+ --test)
494
+ echo " --- TEST MODE ACTIVATED ---"
495
+ # Call the pre-flight checks in test mode
496
+ run_preflight_checks true
497
+ echo " ---------------------------"
498
+ echo " ✅ All configuration checks passed."
499
+ exit 0
500
+ ;;
471
501
esac
472
502
fi
473
503
0 commit comments