文件同步脚本#
脚本说明#
文件同步脚本用于在本地和远程之间同步文件,支持双向同步、增量同步、排除文件等功能。
脚本代码#
#!/bin/bash
# 文件同步脚本
# 功能:在本地和远程之间同步文件
# 作者:System Admin
# 日期:2024-01-01
set -euo pipefail
# 配置变量
LOG_FILE="/var/log/file_sync.log"
SYNC_MODE="push" # push/pull/bidirectional
SOURCE_DIR=""
DEST_DIR=""
EXCLUDE_FILE=""
DRY_RUN=false
VERBOSE=false
DELETE=false
COMPRESS=true
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# 日志函数
log() {
local level=$1
shift
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $@" | tee -a "$LOG_FILE"
}
log_info() {
log "INFO" "$@"
}
log_error() {
log "ERROR" "$@"
}
log_warning() {
log "WARNING" "$@"
}
# 检查rsync
check_rsync() {
if ! command -v rsync &> /dev/null; then
log_error "rsync未安装,请先安装rsync"
return 1
fi
return 0
}
# 检查目录
check_directories() {
if [ ! -d "$SOURCE_DIR" ]; then
log_error "源目录不存在: $SOURCE_DIR"
return 1
fi
# 检查目标目录(远程目录可能不存在)
if [[ ! "$DEST_DIR" =~ ^[a-zA-Z0-9]+@.*:.* ]]; then
if [ ! -d "$DEST_DIR" ]; then
log_error "目标目录不存在: $DEST_DIR"
return 1
fi
fi
return 0
}
# 构建rsync命令
build_rsync_command() {
local cmd="rsync"
# 添加选项
if [ "$DRY_RUN" = true ]; then
cmd="$cmd --dry-run"
fi
if [ "$VERBOSE" = true ]; then
cmd="$cmd -v"
fi
if [ "$DELETE" = true ]; then
cmd="$cmd --delete"
fi
if [ "$COMPRESS" = true ]; then
cmd="$cmd -z"
fi
# 添加基本选项
cmd="$cmd -avz --progress"
# 添加排除文件
if [ -n "$EXCLUDE_FILE" ] && [ -f "$EXCLUDE_FILE" ]; then
cmd="$cmd --exclude-from=$EXCLUDE_FILE"
fi
echo "$cmd"
}
# 推送同步(本地到远程)
push_sync() {
log_info "执行推送同步: $SOURCE_DIR -> $DEST_DIR"
local rsync_cmd=$(build_rsync_command)
$rsync_cmd "$SOURCE_DIR/" "$DEST_DIR/"
}
# 拉取同步(远程到本地)
pull_sync() {
log_info "执行拉取同步: $DEST_DIR -> $SOURCE_DIR"
local rsync_cmd=$(build_rsync_command)
$rsync_cmd "$DEST_DIR/" "$SOURCE_DIR/"
}
# 双向同步
bidirectional_sync() {
log_info "执行双向同步"
# 第一步:推送同步
log_info "第一步:推送同步"
push_sync
# 第二步:拉取同步
log_info "第二步:拉取同步"
pull_sync
log_info "双向同步完成"
}
# 显示同步统计
show_sync_stats() {
log_info "同步统计"
# 查看同步的文件数量
local file_count=$(find "$SOURCE_DIR" -type f | wc -l)
log_info "源目录文件数量: $file_count"
# 查看同步的数据量
local dir_size=$(du -sh "$SOURCE_DIR" | cut -f1)
log_info "源目录大小: $dir_size"
}
# 验证同步
verify_sync() {
log_info "验证同步结果"
# 比较文件数量
local source_count=$(find "$SOURCE_DIR" -type f | wc -l)
local dest_count
if [[ "$DEST_DIR" =~ ^[a-zA-Z0-9]+@.*:.* ]]; then
# 远程目录
local remote_host=$(echo "$DEST_DIR" | cut -d: -f1)
local remote_path=$(echo "$DEST_DIR" | cut -d: -f2)
dest_count=$(ssh "$remote_host" "find '$remote_path' -type f | wc -l")
else
# 本地目录
dest_count=$(find "$DEST_DIR" -type f | wc -l)
fi
log_info "源目录文件数: $source_count"
log_info "目标目录文件数: $dest_count"
if [ $source_count -eq $dest_count ]; then
log_info "同步验证成功"
return 0
else
log_warning "同步验证失败:文件数量不一致"
return 1
fi
}
# 创建排除文件
create_exclude_file() {
local exclude_file="$1"
log_info "创建排除文件: $exclude_file"
{
echo "# 排除临时文件"
echo "*.tmp"
echo "*.temp"
echo "*~"
echo ""
echo "# 排除缓存文件"
echo ".cache"
echo "__pycache__"
echo "node_modules"
echo ""
echo "# 排除日志文件"
echo "*.log"
echo "*.log.*"
echo ""
echo "# 排除系统文件"
echo ".DS_Store"
echo "Thumbs.db"
echo ""
echo "# 排除备份文件"
echo "*.bak"
echo "*.backup"
echo "*~"
} > "$exclude_file"
log_info "排除文件创建完成"
}
# 显示帮助
show_help() {
echo "用法: $0 [选项] <源目录> <目标目录>"
echo ""
echo "选项:"
echo " -m <模式> 同步模式(push/pull/bidirectional,默认: push)"
echo " -e <文件> 排除文件"
echo " -d 删除目标目录中多余的文件"
echo " -c 禁用压缩"
echo " -n 试运行模式(不实际同步)"
echo " -v 详细输出"
echo " -V 验证同步结果"
echo " -h 显示帮助信息"
echo ""
echo "示例:"
echo " # 推送同步(本地到远程)"
echo " $0 /data/ user@remote:/backup/"
echo ""
echo " # 拉取同步(远程到本地)"
echo " $0 -m pull user@remote:/backup/ /data/"
echo ""
echo " # 双向同步"
echo " $0 -m bidirectional /data/ user@remote:/backup/"
echo ""
echo " # 使用排除文件"
echo " $0 -e exclude.txt /data/ user@remote:/backup/"
echo ""
echo " # 删除多余文件"
echo " $0 -d /data/ user@remote:/backup/"
}
# 主函数
main() {
# 解析选项
while getopts "m:e:dcnvVh" opt; do
case $opt in
m)
SYNC_MODE="$OPTARG"
log_info "同步模式: $SYNC_MODE"
;;
e)
EXCLUDE_FILE="$OPTARG"
log_info "排除文件: $EXCLUDE_FILE"
;;
d)
DELETE=true
log_info "启用删除选项"
;;
c)
COMPRESS=false
log_info "禁用压缩"
;;
n)
DRY_RUN=true
log_info "启用试运行模式"
;;
v)
VERBOSE=true
log_info "启用详细输出"
;;
V)
VERIFY=true
log_info "启用验证"
;;
h)
show_help
exit 0
;;
*)
log_error "无效选项: $opt"
show_help
exit 1
;;
esac
done
shift $((OPTIND - 1))
# 检查参数
if [ $# -lt 2 ]; then
log_error "缺少目录参数"
show_help
exit 1
fi
SOURCE_DIR="$1"
DEST_DIR="$2"
# 检查rsync
if ! check_rsync; then
exit 1
fi
# 检查目录
if ! check_directories; then
exit 1
fi
# 显示同步信息
log_info "===== 开始文件同步 ====="
log_info "源目录: $SOURCE_DIR"
log_info "目标目录: $DEST_DIR"
log_info "同步模式: $SYNC_MODE"
if [ "$DRY_RUN" = true ]; then
log_info "[DRY RUN] 试运行模式,不会实际同步文件"
fi
# 执行同步
case $SYNC_MODE in
push)
push_sync
;;
pull)
pull_sync
;;
bidirectional)
bidirectional_sync
;;
*)
log_error "无效的同步模式: $SYNC_MODE"
exit 1
;;
esac
# 显示统计信息
show_sync_stats
# 验证同步
if [ "${VERIFY:-false}" = true ]; then
verify_sync
fi
log_info "===== 文件同步完成 ====="
}
# 执行主函数
main "$@"使用说明#
添加执行权限:
chmod +x file_sync.sh基本用法:
# 推送同步(本地到远程) ./file_sync.sh /data/ user@remote:/backup/ # 拉取同步(远程到本地) ./file_sync.sh -m pull user@remote:/backup/ /data/ # 双向同步 ./file_sync.sh -m bidirectional /data/ user@remote:/backup/高级选项:
# 使用排除文件 ./file_sync.sh -e exclude.txt /data/ user@remote:/backup/ # 删除目标目录中多余的文件 ./file_sync.sh -d /data/ user@remote:/backup/ # 试运行模式(不实际同步) ./file_sync.sh -n /data/ user@remote:/backup/ # 详细输出 ./file_sync.sh -v /data/ user@remote:/backup/ # 验证同步结果 ./file_sync.sh -V /data/ user@remote:/backup/创建排除文件:
# 创建默认排除文件 ./file_sync.sh -e exclude.txt /data/ user@remote:/backup/
功能特点#
- 支持推送、拉取、双向同步
- 增量同步(只传输变化的文件)
- 支持排除文件
- 支持删除多余文件
- 压缩传输
- 试运行模式
- 详细输出
- 同步验证
- 进度显示
依赖项#
- rsync: 用于文件同步
- ssh: 用于远程连接(同步到远程时需要)
注意事项#
- 确保rsync已安装
- 远程同步需要SSH访问权限
- 删除选项(-d)会永久删除文件,谨慎使用
- 建议先使用试运行模式(-n)查看将要同步的文件
- 大文件同步可能需要较长时间
- 确保网络连接稳定