一、为什么需要批量同步?
想象一下,你管理着10台服务器,每次更新网站内容都要手动挨个上传文件,是不是头皮发麻?这就是批量同步要解决的问题。rsync这个老牌工具就像个智能快递员,它能精准识别哪些文件需要更新,只传输变化的部分,大大节省时间和带宽。
举个实际例子:公司官网改版后,需要把新版的HTML/CSS文件同步到5台前端服务器。手动操作不仅容易出错,还特别耗时。这时候,一个自动化的同步脚本就能让你准时下班。
二、准备工作要做好
在写脚本之前,我们需要做些基础工作:
- 确保所有服务器都安装了rsync(Linux系统通常自带)
- 主控机需要配置到所有从机的SSH免密登录
- 统一规划好文件存放路径
配置SSH免密登录的示例(技术栈:Linux Shell):
# 在主控机生成密钥对
ssh-keygen -t rsa -b 4096 # 按回车保持默认设置
# 将公钥拷贝到从机1(重复此步骤配置其他从机)
ssh-copy-id -i ~/.ssh/id_rsa.pub user@slave1_ip
三、脚本编写实战
下面这个脚本实现了核心同步功能,我们逐段分析:
#!/bin/bash
# 技术栈:Linux Shell
# 配置区域:根据实际情况修改
MASTER_DIR="/var/www/project" # 主控机源目录
SLAVES=("192.168.1.101" "192.168.1.102" "192.168.1.103") # 从机IP数组
REMOTE_USER="webadmin" # 远程登录用户名
REMOTE_DIR="/var/www/project" # 从机目标目录
# 日志函数:记录操作过程和错误
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> /var/log/rsync_batch.log
}
# 主同步函数
sync_to_slave() {
local slave_ip=$1
log "开始同步到 $slave_ip"
rsync -avz --delete \
-e "ssh -o StrictHostKeyChecking=no" \
$MASTER_DIR/ $REMOTE_USER@$slave_ip:$REMOTE_DIR
if [ $? -eq 0 ]; then
log "$slave_ip 同步成功"
else
log "$slave_ip 同步失败!错误码:$?"
fi
}
# 主程序入口
log "========== 开始批量同步 =========="
for slave in "${SLAVES[@]}"; do
sync_to_slave $slave
done
log "========== 同步任务完成 =========="
这个脚本有几个亮点:
- 使用数组存储从机IP,方便扩展
- 详细的日志记录功能
--delete参数保持两端完全一致- 错误处理机制
四、进阶功能增强
基础版本能用,但我们可以做得更专业:
- 增加邮件报警功能
- 实现增量备份
- 添加同步前检查
改进后的报警功能示例:
# 在同步函数中添加邮件通知
send_alert() {
local subject=$1
local content=$2
echo "$content" | mail -s "$subject" admin@example.com
}
sync_to_slave() {
# ...原有代码...
if [ $? -ne 0 ]; then
send_alert "同步报警" "主机 $slave_ip 同步失败!"
fi
}
五、实际应用中的技巧
经过多个项目的实践,我总结出这些经验:
- 带宽限制:大文件同步时加上
--bwlimit=5000(单位KB/s) - 网络抖动:添加
--timeout=30参数 - 权限问题:建议统一使用
--chmod=755参数 - 部分同步:可以指定子目录,如
$MASTER_DIR/uploads/
六、常见问题排雷
新手常会遇到这些问题:
权限不足错误:
rsync: mkstemp "/var/www/.index.html.XXXXXX" failed: Permission denied (13)解决方法:确保远程用户对目标目录有写权限
连接超时:
ssh: connect to host 192.168.1.101 port 22: Connection timed out检查:网络连通性、防火墙设置、SSH服务状态
文件校验不一致: 使用
-c参数启用校验模式,但会显著降低速度
七、性能优化建议
当服务器数量多时,这些优化很关键:
并行同步:使用
parallel命令或&后台执行for slave in "${SLAVES[@]}"; do sync_to_slave $slave & done wait差分同步:结合
find命令找出24小时内修改的文件find $MASTER_DIR -type f -mtime -1 > filelist.txt rsync --files-from=filelist.txt ...压缩传输:对于文本文件,
-z参数能减少30%-70%传输量
八、安全注意事项
自动化同步虽方便,但安全不能忽视:
- 使用专用账号:不要用root直接同步
- 限制IP访问:配置从机的SSH只允许主控机IP连接
- 敏感文件过滤:通过
--exclude参数排除配置文件rsync --exclude="*.env" --exclude="config/" ... - 日志审计:定期检查同步日志,发现异常操作
九、完整方案示例
结合所有优化点,这是最终版的脚本:
#!/bin/bash
# 增强版批量同步脚本
# 配置区
MASTER_DIR="/data/website"
SLAVES=("201.120.10.1" "201.120.10.2" "201.120.10.3")
REMOTE_USER="syncuser"
REMOTE_DIR="/data/website"
MAX_THREADS=3 # 最大并发数
# 初始化日志
LOG_FILE="/var/log/sync_$(date +%Y%m%d).log"
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>>$LOG_FILE 2>&1
# 线程控制函数
thread_ctrl() {
while [ $(jobs -r | wc -l) -ge $MAX_THREADS ]; do
sleep 1
done
}
# 带重试机制的同步
sync_with_retry() {
local ip=$1
for i in {1..3}; do
rsync -avz --partial --delete --timeout=30 \
-e "ssh -o ConnectTimeout=10" \
$MASTER_DIR/ $REMOTE_USER@$ip:$REMOTE_DIR
[ $? -eq 0 ] && return 0
sleep $((i*5))
done
return 1
}
# 主流程
echo "==== 启动同步 $(date) ===="
for ip in "${SLAVES[@]}"; do
thread_ctrl
(
if sync_with_retry "$ip"; then
echo "[成功] $ip"
else
echo "[失败] $ip"
# 这里可以添加报警逻辑
fi
) &
done
wait
echo "==== 同步结束 $(date) ===="
十、总结与展望
通过这个方案,我们实现了:
- 一键式多服务器同步
- 完善的错误处理和日志
- 灵活的并发控制
- 自动重试机制
未来还可以考虑:
- 集成到CI/CD流程中
- 增加Web控制界面
- 结合inotify实现实时同步
记住,自动化运维的核心是"懒" - 但不是真的偷懒,而是把时间花在更有价值的事情上。这个脚本可能只需要你半天时间开发,但能节省未来无数个加班的夜晚。
评论