前言
在企业内网环境中,数据库备份的异地容灾是保障数据安全的核心环节。本文针对两台已安装宝塔面板的内网服务器(192.168.3.1 为源服务器,192.168.3.2 为目标服务器),实现仅同步指定数据库(database_1)的最新备份文件的需求,全程基于宝塔面板可视化操作 + Shell 脚本,无需复杂命令行运维,适合运维新手和中小企业使用。
本文核心目标
- 配置源服务器免密登录目标服务器,实现无人值守传输;
- 编写 Shell 脚本,精准筛选database_1的最新备份文件;
- 借助宝塔计划任务,实现定时自动同步 + 自动清理旧备份。
前置条件
- 两台服务器内网互通(可通过
ping 192.168.3.2在 3.1 上测试); - 宝塔面板已正常安装,且源服务器已配置好
longxincrm2数据库的自动备份(宝塔默认备份路径:/www/backup/database)。
第一步:配置源服务器(3.1)免密登录目标服务器(3.2)
脚本中使用scp传输文件时,若未配置免密,会因需要手动输入密码导致定时任务执行失败。这是实现无人值守的核心前提 ,操作全程在3.1 的宝塔终端完成。
1.1 生成 SSH 密钥对
- 登录
192.168.3.1的宝塔面板,点击左侧【终端】,进入命令行界面; - 执行密钥生成命令,全程回车,不设置密码(设置密码会破坏免密逻辑):
bash
ssh-keygen -t rsa
执行完成后,会在/root/.ssh目录下生成两个文件:id_rsa(私钥,本地保留)、id_rsa.pub(公钥,需传至目标服务器)。
1.2 推送公钥至目标服务器(3.2)
1、执行公钥推送命令,将 3.1 的公钥发送到 3.2 的 root 用户下:
bash
ssh-copy-id root@192.168.3.2
2、首次执行会提示确认服务器指纹,输入yes并回车;
3、输入3.2 的 root 密码,回车后即可完成公钥推送。
1.3 验证免密登录是否成功
执行以下命令,尝试登录 3.2:
bash
ssh root@192.168.3.2
若无需输入密码直接进入 3.2 的命令行 ,说明免密配置成功;输入exit即可退出 3.2,返回 3.1 终端。
特殊情况:SSH 端口非默认 22 时的处理
若你的宝塔服务器修改了 SSH 默认端口(如改为 2222),需在上述命令中添加端口参数:
bash
# 生成密钥后,推送公钥时指定端口
ssh-copy-id -p 2222 root@192.168.3.2
# 验证免密时指定端口
ssh -p 2222 root@192.168.3.2
第二步:编写同步的 Shell 脚本
2.1 在计划任务中添加shell脚本,如下图:

bash
#!/bin/bash
# 脚本功能:同步192.168.3.1上database_1的最新数据库备份到192.168.3.2,并清理3.2上7天前的旧备份
# 配置项(根据实际情况修改,若SSH端口非22,仅需修改SCP_PORT)
DB_NAME="database_1" # 需同步的数据库名
BACKUP_DIR="/www/backup/database" # 宝塔默认数据库备份目录
REMOTE_USER="root" # 目标服务器用户名
REMOTE_HOST="192.168.3.2" # 目标服务器内网IP
REMOTE_DIR="/www/backup/database" # 目标服务器备份存储目录
SCP_PORT="22" # SSH端口,默认22,修改过则改为实际端口
# 1. 筛选database_1的最新备份文件
# 匹配规则:db_数据库名_时间戳.sql.gz(宝塔自动备份的文件格式)
LATEST_FILE=$(ls -t ${BACKUP_DIR}/db_${DB_NAME}_*.sql.gz 2>/dev/null | head -1)
# 2. 检查是否找到备份文件
if [ -z "$LATEST_FILE" ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 错误:未找到${DB_NAME}的备份文件!" >> /www/backup/sync_backup.log
exit 1
fi
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 找到最新备份文件:${LATEST_FILE}" >> /www/backup/sync_backup.log
# 3. 传输最新备份文件到目标服务器
if scp -P ${SCP_PORT} "${LATEST_FILE}" ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 备份文件传输成功!" >> /www/backup/sync_backup.log
else
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 错误:备份文件传输失败!" >> /www/backup/sync_backup.log
exit 1
fi
# 4. 清理目标服务器上7天前的database_1旧备份(保留7天,可修改+7为其他天数)
ssh -p ${SCP_PORT} ${REMOTE_USER}@${REMOTE_HOST} "find ${REMOTE_DIR}/db_${DB_NAME}_*.sql.gz -mtime +7 -delete"
if [ $? -eq 0 ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 成功清理${REMOTE_HOST}上7天前的${DB_NAME}旧备份" >> /www/backup/sync_backup.log
else
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 警告:清理${REMOTE_HOST}旧备份失败!" >> /www/backup/sync_backup.log
fi
# 脚本执行完成
exit 0
2.2 手动执行测试(关键步骤)
配置完成后,不要直接等待定时执行,先手动测试脚本是否正常运行:
- 在计划任务列表中,找到刚创建的任务,点击右侧【执行】;
- 点击【查看日志】,查看执行结果;
- 同时登录 3.2 的宝塔面板,进入
/www/backup/database目录,检查是否出现database_1的最新备份文件。
- 执行成功:日志中显示 "找到最新备份文件""传输成功""清理旧备份成功";
- 执行失败:根据日志中的 "错误提示" 排查(如免密配置失败、路径不存在、端口错误)。
第三步:验证与日常维护
3.1 容灾验证
每周手动登录 3.2 服务器,检查备份文件的完整性 (文件大小与 3.1 一致)和时效性(每天都有最新文件),并尝试恢复备份到测试库,验证备份可用。
3.2 日志查看
脚本执行日志会保存在 3.1 的/www/backup/sync_backup.log,若出现同步失败,优先查看该日志定位问题。
常见问题排查
-
scp 传输失败,提示 "Permission denied"
- 原因:免密配置未成功,或 SSH 端口填写错误;
- 解决:重新执行
ssh-copy-id,并核对脚本中的SCP_PORT。
-
未找到备份文件
- 原因:宝塔的数据库自动备份未执行,或备份文件名格式与脚本匹配规则不符;
- 解决:检查宝塔计划任务中的 "备份数据库" 任务是否执行,核对
DB_NAME是否与实际数据库名一致。
-
清理旧备份失败
- 原因:目标服务器的
/www/backup/database目录权限不足; - 解决:在 3.2 的宝塔终端执行
chmod 755 /www/backup/database。
- 原因:目标服务器的
总结
本文通过SSH 免密配置 + 精准筛选 Shell 脚本 + 宝塔计划任务的组合,完美解决了 "宝塔内网服务器仅同步指定数据库最新备份" 的需求。整个方案无需脱离宝塔面板,操作简单、稳定性高,既保证了数据的异地容灾,又避免了无效备份文件的冗余存储。
对于多数据库、多服务器的同步场景,仅需复制脚本并修改DB_NAME和REMOTE_HOST,即可快速扩展,适合中小企业批量部署。