家庭服务器搭建完全指南第8篇:备份策略与监控
Home Server Complete Guide Part 8: Backup Strategy and Monitoring
前言:备份就是保险
运营家庭服务器总会遇到问题。硬盘故障、误删文件、勒索软件感染等数据丢失的风险始终存在。如果你在上一篇完成了安全设置,现在是时候为最坏的情况做准备了。
被问到"你做备份了吗?"时,很多人会回答"当然了",但实际做过恢复测试的人很少。备份不仅仅是复制文件,而是保持可恢复的状态。本篇将介绍系统的备份策略,以及如何搭建在问题发生前就能提前感知的监控系统。
1. 3-2-1备份规则
1.1 什么是3-2-1规则?
被称为数据备份黄金法则的3-2-1规则如下:
- 3份副本:包括原始数据在内至少保持3份副本。
- 2种不同介质:至少备份到2种不同类型的存储介质(如:内置HDD + 外置HDD,SSD + NAS)。
- 1份异地存储:至少1份备份保存在物理上不同的位置(云存储或其他地区的服务器)。
遵循这个规则,即使发生火灾、盗窃、硬件故障等大多数灾难情况,也能恢复数据。
1.2 应用于家庭服务器
以下是在家庭服务器环境中应用3-2-1规则的实际示例:
| 副本 | 存储位置 | 备份方式 | 周期 |
|---|---|---|---|
| 原始 | 服务器主磁盘 | - | - |
| 备份1 | 服务器内另一磁盘或NAS | rsync | 每天 |
| 备份2 | 云存储(Google Drive、Backblaze等) | rclone | 每周 |
2. 使用rsync进行本地备份
2.1 rsync基本用法
rsync是Linux中最常用的文件同步工具。因为只传输更改的文件,所以高效快速。
# 检查rsync安装(大多数系统已预装)
rsync --version
# 基本用法
rsync -av /source/directory/ /backup/directory/
# 主要选项说明
# -a : 归档模式(保留权限、所有者、时间戳等)
# -v : 详细输出
# -z : 压缩传输(远程备份时有用)
# --delete : 同时删除源中已删除的文件
# --exclude : 排除特定文件/目录
# --progress : 显示传输进度
2.2 实用rsync示例
# 备份home目录(排除特定文件)
rsync -av --progress \
--exclude='.cache' \
--exclude='*.tmp' \
--exclude='node_modules' \
/home/username/ /backup/home/
# 备份Docker卷
rsync -av --progress \
/var/lib/docker/volumes/ /backup/docker-volumes/
# 备份到远程服务器(使用SSH)
rsync -avz --progress \
-e "ssh -p 2222" \
/home/username/ user@remote-server:/backup/
# 需要双向同步时(谨慎使用)
rsync -av --delete /source/ /destination/
2.3 实现增量备份
按日期保持增量备份,可以恢复到特定时间点。
# 使用硬链接的增量备份
#!/bin/bash
BACKUP_DIR="/backup/incremental"
SOURCE_DIR="/home/username"
DATE=$(date +%Y-%m-%d)
LATEST="$BACKUP_DIR/latest"
# 如果有之前的备份则使用硬链接
if [ -d "$LATEST" ]; then
rsync -av --delete \
--link-dest="$LATEST" \
"$SOURCE_DIR/" "$BACKUP_DIR/$DATE/"
else
rsync -av "$SOURCE_DIR/" "$BACKUP_DIR/$DATE/"
fi
# 更新latest符号链接
rm -f "$LATEST"
ln -s "$BACKUP_DIR/$DATE" "$LATEST"
# 删除30天以上的备份
find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \;
3. 自动备份脚本(cron)
3.1 编写备份脚本
让我们编写一个系统的备份脚本。
#!/bin/bash
# /usr/local/bin/backup.sh
# 设置
BACKUP_ROOT="/backup"
LOG_FILE="/var/log/backup.log"
DATE=$(date +%Y-%m-%d_%H-%M-%S)
DISCORD_WEBHOOK="YOUR_DISCORD_WEBHOOK_URL"
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 通知函数
notify() {
local message="$1"
local status="$2" # success or error
if [ "$status" = "error" ]; then
color="15158332" # 红色
else
color="3066993" # 绿色
fi
curl -H "Content-Type: application/json" \
-d "{\"embeds\":[{\"title\":\"备份通知\",\"description\":\"$message\",\"color\":$color}]}" \
"$DISCORD_WEBHOOK" 2>/dev/null
}
# 开始备份
log "=== 开始备份 ==="
# 1. 停止Docker容器(保证数据一致性)
log "暂停Docker容器..."
docker-compose -f /home/username/docker-compose.yml stop
# 2. 备份重要目录
DIRS_TO_BACKUP=(
"/home/username/data"
"/var/lib/docker/volumes"
"/etc/nginx"
"/etc/letsencrypt"
)
for dir in "${DIRS_TO_BACKUP[@]}"; do
if [ -d "$dir" ]; then
dest_dir="$BACKUP_ROOT/daily/$(basename $dir)"
log "备份中: $dir -> $dest_dir"
rsync -av --delete "$dir/" "$dest_dir/" 2>&1 | tee -a "$LOG_FILE"
fi
done
# 3. 数据库备份
log "备份数据库..."
mkdir -p "$BACKUP_ROOT/database"
docker exec mysql-container mysqldump -u root -pPASSWORD --all-databases > "$BACKUP_ROOT/database/mysql_$DATE.sql"
# 4. 重启Docker容器
log "重启Docker容器..."
docker-compose -f /home/username/docker-compose.yml start
# 5. 清理旧备份
log "清理旧备份..."
find "$BACKUP_ROOT/database" -name "*.sql" -mtime +7 -delete
# 完成备份
BACKUP_SIZE=$(du -sh "$BACKUP_ROOT" | cut -f1)
log "=== 备份完成(总大小: $BACKUP_SIZE) ==="
notify "备份已成功完成。\n总大小: $BACKUP_SIZE" "success"
3.2 cron设置
# 给脚本添加执行权限
sudo chmod +x /usr/local/bin/backup.sh
# 编辑crontab
sudo crontab -e
# 每天凌晨3点执行备份
0 3 * * * /usr/local/bin/backup.sh
# 每周日凌晨4点执行云备份
0 4 * * 0 /usr/local/bin/cloud-backup.sh
# 查看cron日志
grep CRON /var/log/syslog
提示:要确认cron任务是否正常运行,可以先设置较短的间隔,确认正常运行后再更改为所需的周期。
4. 云备份(rclone)
4.1 rclone安装和设置
rclone是一个可以在命令行管理各种云存储的工具。支持Google Drive、Dropbox、OneDrive、AWS S3、Backblaze B2等数十种服务。
# 安装rclone
curl https://rclone.org/install.sh | sudo bash
# 或使用apt安装
sudo apt install rclone
# 配置rclone(交互式)
rclone config
4.2 Google Drive设置示例
# 运行rclone config后
# n) New remote 选择
# name> gdrive
# Storage> drive (Google Drive)
# client_id> (回车使用默认值或输入自己的ID)
# client_secret> (回车使用默认值)
# scope> 1 (Full access)
# root_folder_id> (回车)
# service_account_file> (回车)
# Edit advanced config? n
# Use auto config? y (通过Web浏览器认证)
# Configure as team drive? n
# 确认设置
rclone listremotes
# 测试连接
rclone lsd gdrive:
4.3 rclone备份脚本
#!/bin/bash
# /usr/local/bin/cloud-backup.sh
BACKUP_SOURCE="/backup/daily"
REMOTE_NAME="gdrive"
REMOTE_PATH="homeserver-backup"
LOG_FILE="/var/log/cloud-backup.log"
DATE=$(date +%Y-%m-%d)
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=== 开始云备份 ==="
# 同步备份目录
rclone sync "$BACKUP_SOURCE" "$REMOTE_NAME:$REMOTE_PATH/$DATE" \
--progress \
--transfers 4 \
--checkers 8 \
--log-file="$LOG_FILE" \
--log-level INFO
# 删除旧的云备份(30天以上)
log "清理旧的云备份..."
rclone delete "$REMOTE_NAME:$REMOTE_PATH" \
--min-age 30d \
--log-file="$LOG_FILE"
# 检查使用量
USAGE=$(rclone about "$REMOTE_NAME:" --json | jq -r '.used // 0')
log "=== 云备份完成(使用量: $USAGE bytes) ==="
4.4 加密备份
重要数据在上传到云端之前最好加密。
# rclone crypt设置
rclone config
# n) New remote
# name> gdrive-crypt
# Storage> crypt
# remote> gdrive:encrypted-backup
# filename_encryption> standard
# directory_name_encryption> true
# Password> (输入强密码)
# Salt> (回车自动生成)
# 使用加密备份
rclone sync /backup/sensitive gdrive-crypt:
5. 系统监控工具
5.1 htop - 进程监视器
htop是在终端中使用的交互式进程查看器。
# 安装htop
sudo apt install htop
# 运行
htop
# 主要快捷键
# F2: 设置
# F3: 搜索
# F4: 过滤
# F5: 树状视图
# F6: 排序
# F9: 发送信号 (kill)
# F10: 退出
5.2 glances - 综合系统监视器
glances是比htop提供更多信息的工具。
# 安装glances
sudo apt install glances
# 或使用pip安装(最新版本)
pip3 install glances
# 基本运行
glances
# Web服务器模式运行(远程监控)
glances -w -p 61208
# 包含Docker容器监控
glances --enable-plugin docker
# 定期保存报告
glances --export csv --export-csv-file /var/log/glances.csv
5.3 netdata - 实时Web仪表板
netdata提供漂亮的Web界面和实时监控。
# 安装netdata(官方脚本)
wget -O /tmp/netdata-kickstart.sh https://my-netdata.io/kickstart.sh
bash /tmp/netdata-kickstart.sh
# 检查服务状态
sudo systemctl status netdata
# 访问Web界面(默认端口:19999)
# http://服务器IP:19999
# 配置文件位置
# /etc/netdata/netdata.conf
# 告警设置
# /etc/netdata/health_alarm_notify.conf
# netdata Discord告警设置
sudo nano /etc/netdata/health_alarm_notify.conf
# 添加/修改以下内容
SEND_DISCORD="YES"
DISCORD_WEBHOOK_URL="YOUR_DISCORD_WEBHOOK_URL"
DEFAULT_RECIPIENT_DISCORD="alerts"
6. Grafana + Prometheus监控栈
6.1 使用Docker Compose安装
要搭建专业的监控环境,Grafana和Prometheus的组合是标准方案。
# docker-compose-monitoring.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'
- '--storage.tsdb.retention.time=15d'
ports:
- "9090:9090"
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=your_secure_password
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- "3000:3000"
restart: unless-stopped
depends_on:
- prometheus
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- "9100:9100"
restart: unless-stopped
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
restart: unless-stopped
volumes:
prometheus_data:
grafana_data:
6.2 Prometheus配置
# prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets: []
rule_files: []
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
# 运行栈
docker-compose -f docker-compose-monitoring.yml up -d
# Grafana访问: http://服务器IP:3000
# 默认账户: admin / your_secure_password
# 在Grafana中添加Prometheus数据源
# Configuration > Data Sources > Add data source > Prometheus
# URL: http://prometheus:9090
6.3 实用的Grafana仪表板
Grafana仪表板可以自己创建,也可以导入社区共享的仪表板。
- Node Exporter Full (ID: 1860):系统全面监控
- Docker Container Monitoring (ID: 193):Docker容器监控
- Nginx (ID: 9614):Nginx Web服务器监控
# 导入仪表板
# Grafana > Dashboards > Import
# 输入Dashboard ID后Load
# 选择Prometheus数据源后Import
7. 告警设置
7.1 Discord Webhook告警
#!/bin/bash
# /usr/local/bin/discord-notify.sh
WEBHOOK_URL="YOUR_DISCORD_WEBHOOK_URL"
send_notification() {
local title="$1"
local message="$2"
local color="${3:-3447003}" # 默认蓝色
curl -H "Content-Type: application/json" \
-d "{
\"embeds\": [{
\"title\": \"$title\",
\"description\": \"$message\",
\"color\": $color,
\"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"
}]
}" \
"$WEBHOOK_URL"
}
# 使用示例
# send_notification "服务器告警" "备份已完成。" "3066993" # 绿色
# send_notification "警告" "磁盘使用率超过90%" "15158332" # 红色
7.2 Telegram机器人告警
#!/bin/bash
# /usr/local/bin/telegram-notify.sh
BOT_TOKEN="YOUR_BOT_TOKEN"
CHAT_ID="YOUR_CHAT_ID"
send_telegram() {
local message="$1"
curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
-d chat_id="$CHAT_ID" \
-d text="$message" \
-d parse_mode="HTML"
}
# 使用示例
# send_telegram "服务器告警
# 备份已完成。
# 时间: $(date)"
7.3 系统状态告警脚本
#!/bin/bash
# /usr/local/bin/system-check.sh
source /usr/local/bin/discord-notify.sh
# 检查磁盘使用率
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -gt 85 ]; then
send_notification "磁盘警告" "根分区使用率: ${DISK_USAGE}%" "15158332"
fi
# 检查内存使用率
MEM_USAGE=$(free | awk '/Mem:/ {printf "%.0f", $3/$2 * 100}')
if [ "$MEM_USAGE" -gt 90 ]; then
send_notification "内存警告" "内存使用率: ${MEM_USAGE}%" "15158332"
fi
# 检查服务状态
SERVICES=("docker" "nginx" "ssh")
for service in "${SERVICES[@]}"; do
if ! systemctl is-active --quiet "$service"; then
send_notification "服务宕机" "$service 服务已停止!" "15158332"
fi
done
# 检查负载
LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $1}' | tr -d ' ')
CPU_CORES=$(nproc)
LOAD_INT=${LOAD%.*}
if [ "$LOAD_INT" -gt "$CPU_CORES" ]; then
send_notification "负载警告" "系统负载: $LOAD (CPU核心: $CPU_CORES)" "15105570"
fi
# 注册到cron(每5分钟检查)
sudo crontab -e
*/5 * * * * /usr/local/bin/system-check.sh
8. 故障响应与恢复流程
8.1 故障响应检查清单
服务器故障发生时,请提前准备好检查清单以免慌张。
- 确认问题:哪些服务受到影响?
- 检查日志:查看journalctl、/var/log/
- 检查资源:CPU、内存、磁盘空间
- 检查网络:连接状态、防火墙规则
- 最近更改:是否有更新、配置更改
- 重启服务:重启相关服务或服务器
- 回滚:必要时恢复到之前的状态
8.2 从备份恢复
# 从rsync备份恢复
sudo rsync -av --progress /backup/daily/data/ /home/username/data/
# 数据库恢复
docker exec -i mysql-container mysql -u root -pPASSWORD < /backup/database/mysql_2026-01-22.sql
# 从云备份恢复
rclone copy gdrive:homeserver-backup/2026-01-22 /restore/ --progress
# Docker卷恢复
sudo systemctl stop docker
sudo rsync -av /backup/docker-volumes/ /var/lib/docker/volumes/
sudo systemctl start docker
8.3 恢复测试的重要性
只做备份不做恢复测试,到实际情况时可能会手忙脚乱。请定期进行恢复测试。
# 恢复测试脚本示例
#!/bin/bash
# /usr/local/bin/recovery-test.sh
TEST_DIR="/tmp/recovery-test-$(date +%Y%m%d)"
mkdir -p "$TEST_DIR"
echo "=== 开始备份恢复测试 ==="
# 1. 本地备份测试
echo "从本地备份恢复示例文件中..."
rsync -av /backup/daily/data/sample-file.txt "$TEST_DIR/"
if [ -f "$TEST_DIR/sample-file.txt" ]; then
echo "本地备份恢复成功"
else
echo "本地备份恢复失败!"
fi
# 2. 云备份测试
echo "从云备份恢复示例文件中..."
rclone copy gdrive:homeserver-backup/latest/sample-file.txt "$TEST_DIR/cloud/"
if [ -f "$TEST_DIR/cloud/sample-file.txt" ]; then
echo "云备份恢复成功"
else
echo "云备份恢复失败!"
fi
# 清理
rm -rf "$TEST_DIR"
echo "=== 恢复测试完成 ==="
结语
备份和监控在平时可能不太引人注意,但在出现问题时会发挥其价值。即使觉得麻烦,也请按照3-2-1规则建立备份体系,通过监控系统随时掌握服务器状态。
特别重要的是保持"可恢复"的备份。即使有备份文件,如果无法恢复也没有意义。定期进行恢复测试,并记录恢复流程是最好的做法。
家庭服务器搭建完全指南系列到此结束。从硬件选择到操作系统安装、网络设置、Docker、安全,以及备份和监控,我们涵盖了家庭服务器运营所需的核心内容。希望本指南对您的家庭服务器之旅有所帮助。
如有其他问题或疑问,请在评论中留言!