Skip to content

Commit 042a6e7

Browse files
authored
Update README.md
1 parent f803b65 commit 042a6e7

File tree

1 file changed

+40
-34
lines changed

1 file changed

+40
-34
lines changed

README.md

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,9 @@ To run the backup automatically, edit the root crontab.
155155
# !! IMPORTANT !! Set file permissions to 600 (chmod 600 backup.conf)
156156
157157
# --- Source and Destination ---
158-
# IMPORTANT: LOCAL_DIR must end with a trailing slash!
159-
LOCAL_DIR="/home/user/"
158+
# List all source directories to back up, separated by spaces.
159+
# IMPORTANT: Each path MUST end with a trailing slash!
160+
BACKUP_DIRS="/home/user/ /usr/scripts/ /etc/apps/"
160161
BOX_DIR="/home/myvps/"
161162
162163
# --- Connection Details ---
@@ -221,7 +222,7 @@ END_EXCLUDES
221222

222223
# =================================================================
223224
# SCRIPT INITIALIZATION & SETUP
224-
# v0.8 - 2025.08.09
225+
# v0.9 - 2025.08.09
225226
# =================================================================
226227
set -Euo pipefail
227228
umask 077
@@ -266,7 +267,7 @@ else
266267
fi
267268

268269
# --- Validate that all required configuration variables are set ---
269-
for var in LOCAL_DIR BOX_DIR HETZNER_BOX SSH_OPTS_STR LOG_FILE \
270+
for var in BACKUP_DIRS BOX_DIR HETZNER_BOX SSH_OPTS_STR LOG_FILE \
270271
NTFY_PRIORITY_SUCCESS NTFY_PRIORITY_WARNING NTFY_PRIORITY_FAILURE \
271272
LOG_RETENTION_DAYS; do
272273
if [ -z "${!var:-}" ]; then
@@ -329,7 +330,8 @@ send_notification() {
329330

330331
run_integrity_check() {
331332
local rsync_check_opts=(-ainc -c --delete --exclude-from="$EXCLUDE_FILE_TMP" --out-format="%n" -e "ssh ${SSH_OPTS_STR:-}")
332-
LC_ALL=C rsync "${rsync_check_opts[@]}" "$LOCAL_DIR" "$REMOTE_TARGET" 2>> "${LOG_FILE:-/dev/null}"
333+
# shellcheck disable=SC2086
334+
LC_ALL=C rsync "${rsync_check_opts[@]}" $BACKUP_DIRS "$REMOTE_TARGET" 2>> "${LOG_FILE:-/dev/null}"
333335
}
334336

335337
parse_stat() {
@@ -389,10 +391,12 @@ if ! ssh ${SSH_OPTS_STR:-} -o BatchMode=yes -o ConnectTimeout=10 "$HETZNER_BOX"
389391
trap - ERR; exit 6
390392
fi
391393

392-
if [[ ! -d "$LOCAL_DIR" ]] || [[ "$LOCAL_DIR" != */ ]]; then
393-
send_notification "❌ Backup FAILED: ${HOSTNAME}" "x" "${NTFY_PRIORITY_FAILURE}" "failure" "FATAL: LOCAL_DIR must exist and end with a trailing slash ('/')."
394-
trap - ERR; exit 2
395-
fi
394+
for dir in $BACKUP_DIRS; do
395+
if [[ ! -d "$dir" ]] || [[ "$dir" != */ ]]; then
396+
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 ('/')."
397+
trap - ERR; exit 2
398+
fi
399+
done
396400

397401

398402
# =================================================================
@@ -411,37 +415,38 @@ if [[ "${1:-}" ]]; then
411415
--dry-run)
412416
trap - ERR
413417
echo "--- DRY RUN MODE ACTIVATED ---"
414-
if ! rsync "${RSYNC_BASE_OPTS[@]}" --dry-run --info=progress2 "$LOCAL_DIR" "$REMOTE_TARGET"; then
418+
# shellcheck disable=SC2086
419+
if ! rsync "${RSYNC_BASE_OPTS[@]}" --dry-run --info=progress2 $BACKUP_DIRS "$REMOTE_TARGET"; then
415420
echo ""
416421
echo "❌ Dry run FAILED. See the rsync error message above for details."
417422
exit 1
418423
fi
419424
echo "--- DRY RUN COMPLETED ---"; exit 0 ;;
420-
--checksum)
425+
--checksum | --summary)
426+
# Both modes use the same check, just with different reporting
421427
echo "--- INTEGRITY CHECK MODE ACTIVATED ---"
422-
echo "Comparing checksums... this may take a while."
428+
echo "Calculating differences..."
423429
FILE_DISCREPANCIES=$(run_integrity_check)
424-
if [ -z "$FILE_DISCREPANCIES" ]; then
425-
echo "✅ Checksum validation passed. No discrepancies found."
426-
log_message "Checksum validation passed. No discrepancies found."
427-
send_notification "✅ Backup Integrity OK: ${HOSTNAME}" "white_check_mark" "${NTFY_PRIORITY_SUCCESS}" "success" "Checksum validation passed. No discrepancies found."
428-
else
429-
log_message "Backup integrity check FAILED. Found discrepancies."
430-
ISSUE_LIST=$(echo "${FILE_DISCREPANCIES}" | head -n 10)
431-
printf "❌ Backup integrity check FAILED. First 10 differing files:\n%s\n" "${ISSUE_LIST}"
432-
printf -v FAILURE_MSG "Backup integrity check FAILED.\n\nFirst 10 differing files:\n%s\n\nCheck log for full details." "${ISSUE_LIST}"
433-
send_notification "❌ Backup Integrity FAILED: ${HOSTNAME}" "x" "${NTFY_PRIORITY_FAILURE}" "failure" "${FAILURE_MSG}"
430+
431+
if [[ "$1" == "--summary" ]]; then
432+
MISMATCH_COUNT=$(echo "$FILE_DISCREPANCIES" | wc -l)
433+
printf "🚨 Total files with checksum mismatches: %d\n" "$MISMATCH_COUNT"
434+
log_message "Summary mode check found $MISMATCH_COUNT mismatched files."
435+
send_notification "📊 Backup Summary: ${HOSTNAME}" "bar_chart" "${NTFY_PRIORITY_SUCCESS}" "success" "Mismatched files found: $MISMATCH_COUNT"
436+
else # --checksum
437+
if [ -z "$FILE_DISCREPANCIES" ]; then
438+
echo "✅ Checksum validation passed. No discrepancies found."
439+
log_message "Checksum validation passed. No discrepancies found."
440+
send_notification "✅ Backup Integrity OK: ${HOSTNAME}" "white_check_mark" "${NTFY_PRIORITY_SUCCESS}" "success" "Checksum validation passed. No discrepancies found."
441+
else
442+
log_message "Backup integrity check FAILED. Found discrepancies."
443+
ISSUE_LIST=$(echo "${FILE_DISCREPANCIES}" | head -n 10)
444+
printf "❌ Backup integrity check FAILED. First 10 differing files:\n%s\n" "${ISSUE_LIST}"
445+
printf -v FAILURE_MSG "Backup integrity check FAILED.\n\nFirst 10 differing files:\n%s\n\nCheck log for full details." "${ISSUE_LIST}"
446+
send_notification "❌ Backup Integrity FAILED: ${HOSTNAME}" "x" "${NTFY_PRIORITY_FAILURE}" "failure" "${FAILURE_MSG}"
447+
fi
434448
fi
435449
exit 0 ;;
436-
437-
--summary)
438-
echo "--- INTEGRITY SUMMARY MODE ---"
439-
echo "Calculating differences..."
440-
MISMATCH_COUNT=$(run_integrity_check | wc -l)
441-
printf "🚨 Total files with checksum mismatches: %d\n" "$MISMATCH_COUNT"
442-
log_message "Summary mode check found $MISMATCH_COUNT mismatched files."
443-
send_notification "📊 Backup Summary: ${HOSTNAME}" "bar_chart" "${NTFY_PRIORITY_SUCCESS}" "success" "Mismatched files found: $MISMATCH_COUNT"
444-
exit 0 ;;
445450
esac
446451
fi
447452

@@ -451,7 +456,6 @@ flock -n 200 || { echo "Another instance is running, exiting."; exit 5; }
451456
if [ -f "$LOG_FILE" ] && [ "$(stat -c%s "$LOG_FILE")" -gt "$MAX_LOG_SIZE" ]; then
452457
mv "$LOG_FILE" "${LOG_FILE}.$(date +%Y%m%d_%H%M%S)"
453458
touch "$LOG_FILE"
454-
# Clean up old log files
455459
find "$(dirname "$LOG_FILE")" -name "$(basename "$LOG_FILE").*" -type f -mtime +"$LOG_RETENTION_DAYS" -delete
456460
fi
457461

@@ -466,11 +470,13 @@ RSYNC_OPTS=("${RSYNC_BASE_OPTS[@]}")
466470

467471
if [[ "$VERBOSE_MODE" == "true" ]]; then
468472
RSYNC_OPTS+=(--info=stats2,progress2)
469-
nice -n 19 ionice -c 3 rsync "${RSYNC_OPTS[@]}" "$LOCAL_DIR" "$REMOTE_TARGET" 2>&1 | tee "$RSYNC_LOG_TMP"
473+
# shellcheck disable=SC2086
474+
nice -n 19 ionice -c 3 rsync "${RSYNC_OPTS[@]}" $BACKUP_DIRS "$REMOTE_TARGET" 2>&1 | tee "$RSYNC_LOG_TMP"
470475
RSYNC_EXIT_CODE=${PIPESTATUS[0]}
471476
else
472477
RSYNC_OPTS+=(--info=stats2)
473-
nice -n 19 ionice -c 3 rsync "${RSYNC_OPTS[@]}" "$LOCAL_DIR" "$REMOTE_TARGET" > "$RSYNC_LOG_TMP" 2>&1 || RSYNC_EXIT_CODE=$?
478+
# shellcheck disable=SC2086
479+
nice -n 19 ionice -c 3 rsync "${RSYNC_OPTS[@]}" $BACKUP_DIRS "$REMOTE_TARGET" > "$RSYNC_LOG_TMP" 2>&1 || RSYNC_EXIT_CODE=$?
474480
fi
475481

476482
END_TIME=$(date +%s)

0 commit comments

Comments
 (0)