Files
gniza4cp/lib/verify.sh
shuki 1459bd1b8b Initial commit: gniza backup & disaster recovery CLI + WHM plugin
Full-featured cPanel backup tool with SSH, S3, and Google Drive support.
Includes WHM plugin with Tailwind/DaisyUI UI, multi-remote management,
decoupled schedules, and account restore workflows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 02:39:39 +02:00

133 lines
4.4 KiB
Bash

#!/usr/bin/env bash
# gniza/lib/verify.sh — Remote backup integrity checks
verify_account_backup() {
local user="$1"
local timestamp="${2:-}"
local errors=0
# Resolve timestamp
local ts; ts=$(resolve_snapshot_timestamp "$user" "$timestamp") || return 1
log_info "Verifying backup for $user (snapshot: $ts)..."
if _is_rclone_mode; then
local snap_subpath="accounts/${user}/snapshots/${ts}"
# Check .complete marker
if ! rclone_exists "${snap_subpath}/.complete"; then
log_error "Snapshot missing .complete marker: $snap_subpath"
return 1
fi
# Count files
local file_list; file_list=$(rclone_list_files "$snap_subpath" 2>/dev/null) || true
local file_count=0
[[ -n "$file_list" ]] && file_count=$(echo "$file_list" | wc -l)
if (( file_count == 0 )); then
log_warn "No files found in snapshot"
((errors++)) || true
else
log_info " files: $file_count file(s)"
fi
# Check homedir
if rclone_exists "${snap_subpath}/homedir/"; then
local size_json; size_json=$(rclone_size "${snap_subpath}/homedir" 2>/dev/null) || true
local bytes=0
if [[ -n "$size_json" ]]; then
bytes=$(echo "$size_json" | grep -oP '"bytes":\s*\K[0-9]+' || echo 0)
fi
log_info " homedir: $(human_size "$bytes")"
else
log_warn "homedir directory missing in snapshot"
fi
# Check latest.txt
local latest; latest=$(rclone_cat "accounts/${user}/snapshots/latest.txt" 2>/dev/null) || true
if [[ -n "$latest" ]]; then
log_info " latest -> $latest"
else
log_warn " latest.txt not set"
fi
else
local snap_dir; snap_dir=$(get_snapshot_dir "$user")
local snap_path="$snap_dir/$ts"
# Check snapshot directory exists
if ! remote_exec "test -d '$snap_path'" 2>/dev/null; then
log_error "Snapshot directory not found: $snap_path"
return 1
fi
# Detect old format (pkgacct/ subdir) vs new format (content at root)
local pkgacct_base="$snap_path"
if remote_exec "test -d '$snap_path/pkgacct'" 2>/dev/null; then
pkgacct_base="$snap_path/pkgacct"
fi
# Check for expected pkgacct files
local file_count; file_count=$(remote_exec "find '$pkgacct_base' -maxdepth 1 -type f | wc -l" 2>/dev/null)
if [[ "$file_count" -eq 0 ]]; then
log_warn "No pkgacct files found in snapshot"
((errors++)) || true
else
log_info " pkgacct: $file_count file(s)"
fi
# Check for SQL files
local sql_count; sql_count=$(remote_exec "find '$pkgacct_base/mysql' -name '*.sql.gz' 2>/dev/null | wc -l" 2>/dev/null)
log_info " databases: $sql_count compressed SQL file(s)"
# Check homedir directory
if ! remote_exec "test -d '$snap_path/homedir'" 2>/dev/null; then
log_warn "homedir directory missing in snapshot"
else
local homedir_size; homedir_size=$(remote_exec "du -sb '$snap_path/homedir' | cut -f1" 2>/dev/null)
log_info " homedir: $(human_size "${homedir_size:-0}")"
fi
# Check latest symlink
local base; base=$(get_remote_account_base "$user")
local latest_target; latest_target=$(remote_exec "readlink '$base/latest' 2>/dev/null" 2>/dev/null)
if [[ -n "$latest_target" ]]; then
log_info " latest -> $(basename "$latest_target")"
else
log_warn " latest symlink not set"
fi
fi
if (( errors > 0 )); then
log_error "Verification found $errors issue(s) for $user"
return 1
fi
log_info "Verification passed for $user"
return 0
}
verify_all_accounts() {
local accounts; accounts=$(list_remote_accounts)
local total=0 passed=0 failed=0
if [[ -z "$accounts" ]]; then
log_warn "No remote accounts found to verify"
return 0
fi
while IFS= read -r user; do
[[ -z "$user" ]] && continue
((total++)) || true
if verify_account_backup "$user"; then
((passed++)) || true
else
((failed++)) || true
fi
done <<< "$accounts"
echo ""
log_info "Verification complete: $passed/$total passed, $failed failed"
(( failed > 0 )) && return 1
return 0
}