Linux 备份与监控自动化:完整性、恢复和外部告警验证
服务器运维需要能够恢复的备份,也需要能发现故障的状态检查。应分别验证归档生成、完整性、实际恢复、HTTP 响应与可用空间,并从服务器外部检测失败和任务未执行的情况。
先完成手动备份与恢复验证,再接入定时执行。备份生成、独立恢复和失败报告都要核验,不能仅凭定时器已启用就认定备份可靠。
参考环境为常规安装的 Ubuntu 26.04 LTS 或 Rocky Linux 9 系列虚拟机。容器、Windows Subsystem for Linux(WSL)和其他版本的服务与软件包配置可能不同;先按虚拟机环境准备(英语)记录版本并准备控制台恢复。
明确保护的数据与恢复范围
示例面向变更受控的普通静态文件,例如Nginx 静态站点的内容。服务配置、证书、域名系统(DNS)信息和部署流程要另行备份及记录;数据库应使用对应产品保证一致性的备份方式。本机归档用于学习流程,不能单独抵御服务器磁盘故障或账号失陷。
选择当前用户可读取的专用内容目录,以及仅授权账号可写的备份目录。不要为了读取受保护文件,就把整个脚本随意安排为 root 运行。生产备份还需明确专用账号、允许访问的路径、加密密钥管理及保留策略。
创建显式接收源目录和目标目录的脚本
需要 Bash、GNU tar、realpath、mktemp、sha256sum 和 date。先检查 $HOME/bin/course-backup.sh 是否已有内容,避免覆盖;逐条写入并检查,目录创建或文件写入失败就停止。
mkdir -p "$HOME/bin"
cat > "$HOME/bin/course-backup.sh" <<'EOF'
#!/usr/bin/env bash
set -u
set -o pipefail
umask 077
if (( $# != 2 )); then
printf "Usage: %s SOURCE_DIRECTORY BACKUP_DIRECTORY\n" "$0" >&2
exit 2
fi
source_dir=$(realpath -e -- "$1") || exit 1
backup_dir=$(realpath -e -- "$2") || exit 1
[[ -d "$source_dir" && -d "$backup_dir" ]] || exit 1
[[ "$source_dir" != / ]] || { printf "Use a dedicated static-content directory\n" >&2; exit 1; }
case "$backup_dir/" in
"$source_dir/"*) printf "Backup must be outside source\n" >&2; exit 1 ;;
esac
work=$(mktemp -d "$backup_dir/backup.XXXXXXXX") || exit 1
if ! tar -czf "$work/data.tar.gz" -C "$source_dir" .; then
printf "Archive failed: %s\n" "$work" >&2; exit 1
fi
if ! tar -tzf "$work/data.tar.gz" > /dev/null; then
printf "Archive listing failed\n" >&2; exit 1
fi
if ! (cd "$work" && sha256sum data.tar.gz > data.tar.gz.sha256); then
printf "Checksum creation failed\n" >&2; exit 1
fi
if ! date --iso-8601=seconds > "$work/created-at.txt"; then exit 1; fi
printf "complete\n" > "$work/COMPLETE" || exit 1
printf "Backup ready: %s\n" "$work"
EOF
bash -n "$HOME/bin/course-backup.sh"
脚本把现有目录转换为规范路径,拒绝将根目录 / 作为此静态内容练习的源,也拒绝把备份写入源目录内部。每次用 mktemp 创建唯一目录,避免同名归档碰撞;这不等于锁定源数据或生成一致性快照,备份期间仍应控制写入。
应结合脚本成功退出与 COMPLETE 内容为 complete 来确认归档步骤完成,不能只检查标记文件存在:磁盘写入失败可能留下空标记。这个标记也不是已经做过恢复演练的证明。失败可能留下部分目录,应调查原因,不计为可用恢复点。创建时间会记录,但脚本不会自动删除旧备份;校验和与归档存放在一起,也不能抵御能够同时篡改两者的攻击者。
分别测试生成、完整性与恢复
在交互式练习终端或专用脚本中执行下面代码;失败分支的 exit 会结束当前 shell。临时目录创建失败后必须立即停止,避免把空变量拼成其他位置的路径。
lab=$(mktemp -d "$HOME/linux-ops-lab.XXXXXX") || exit 1
mkdir "$lab/site" "$lab/backups" "$lab/restored" || exit 1
printf "site version 1\n" > "$lab/site/index.html" || exit 1
bash "$HOME/bin/course-backup.sh" "$lab/site" "$lab/backups" || exit 1
find "$lab/backups" -maxdepth 2 -type f -print
把本次输出中 Backup ready: 后的真实路径填入下面变量;路径含空格时要用引号包围,不能照抄占位符。逐条执行,任一检查失败都停止,不要继续解包。校验和及tar 目录列表成功,仍不能证明应用已经恢复。
backup=ACTUAL_BACKUP_DIRECTORY
test -f "$backup/COMPLETE"
(cd "$backup" && sha256sum -c data.tar.gz.sha256)
tar -xzf "$backup/data.tar.gz" -C "$lab/restored"
diff -r "$lab/site" "$lab/restored"
预期结果是 COMPLETE 存在、校验显示 OK、diff 不报告差异。恢复到空目录后,另外核对权限、所有者和所需安全标签,并实际测试网页服务。迁移到独立存储后也要重复校验和恢复;空间紧张时按保留策略保护必要恢复点,不要批量删除旧副本。
创建 HTTP 与存储空间检查脚本
需要 curl、GNU df 与 awk。脚本接收 URL、最低可用空间 KiB 和所检查的存储路径,只把 HTTP 200~299 视为正常。它不跟随重定向,也不检查响应正文、数据库或全部应用功能;若预期返回重定向或需要认证,应先调整检查标准。
cat > "$HOME/bin/course-health.sh" <<'EOF'
#!/usr/bin/env bash
set -u
set -o pipefail
if (( $# != 3 )); then
printf "Usage: %s URL MIN_FREE_KIB STORAGE_PATH\n" "$0" >&2; exit 2
fi
url=$1
minimum=$2
path=$3
[[ "$minimum" =~ ^[0-9]{1,18}$ ]] || exit 2
if ! status=$(curl -sS -o /dev/null -w "%{http_code}" --connect-timeout 5 --max-time 15 "$url"); then
printf "HTTP transport failed\n" >&2; exit 1
fi
[[ "$status" =~ ^2[0-9][0-9]$ ]] || { printf "HTTP status=%s\n" "$status" >&2; exit 1; }
available=$(df -Pk -- "$path" | awk 'NR==2 {print $4}') || exit 1
[[ "$available" =~ ^[0-9]{1,18}$ ]] || exit 1
(( 10#$available >= 10#$minimum )) || { printf "Low storage: %s KiB\n" "$available" >&2; exit 1; }
printf "OK http=%s free_kib=%s\n" "$status" "$available"
EOF
bash -n "$HOME/bin/course-health.sh"
bash "$HOME/bin/course-health.sh" http://127.0.0.1/ 102400 "$HOME"
这里每个空间数值限定为 1~18 位十进制数字,以避免 64 位 Bash 对超长整数计算时发生未检查的溢出。10# 明确采用十进制,允许输入前导零。此示例面向 64 位 Bash,不适合把数值上限直接套用到其他算术环境。
df -Pk 检查指定路径所在文件系统的可用空间;102400 KiB 等于 100 MiB,仅是练习阈值,并非生产建议。应结合增长速度和恢复所需空间设定,另行检查 inode;块空间足够也可能因 inode 耗尽而无法创建文件。
名称型 Nginx 站点应使用真实域名 URL 或正确的 Host 路由。示例的回环地址可能访问默认站点,默认站点返回 200 不能证明目标站点正常。还要确认 curl 实际使用的代理与网络路径,区分本机可用和外部用户可用。
接入定时器并独立检测失败
复用前文用户 service、timer 的完整结构,将 ExecStart 设置为 /bin/bash %h/bin/course-backup.sh ACTUAL_SOURCE ACTUAL_BACKUP_PATH,替换实际路径。路径含空格时按 systemd 命令行规则分别引用各参数,不要当作任意 shell 命令串。先手动执行同一命令,再按数据变更量和恢复目标确定周期,状态检查使用独立单元。
分别查看下次触发、服务退出状态及最后一次完成备份的时间。相同服务器上的监控会随服务器停机而停止,应由外部监控检查真实 URL 和备份新鲜度,检测“没有按时执行”,不能只检测已启动任务的退出码。邮件或消息告警需测试真实收件路径,明确响应人员与恢复操作。
逐项演练失败并清理实验
每次只改变一个条件:使用不存在的源目录、请求不存在的 HTTP 资源,或设置大于当前可用空间但在允许数字范围内的阈值。确认均以失败退出,再恢复原值重试;还要确认未生成 COMPLETE 的部分归档不会被报告为成功。
先停止并禁用实验定时器,确认相关服务不再运行,再只清理本次创建的脚本与工作目录。若仍需分析失败,应先保留相关日志和部分归档,不要影响既有备份任务及其恢复点。




