Unison是一个双向文件同步工具,允许两个或多个位置(可以是本地目录或远程服务器)保持文件一致。它支持跨平台同步,具有智能冲突检测和解决机制,是保持多台计算机文件同步的理想工具。
两个方向的同步,保持文件一致性
支持Linux, Windows, macOS
通过SSH加密传输数据
只传输有变化的文件部分
智能检测和解决文件冲突
保留文件历史版本
# 安装unison
sudo apt update
sudo apt install unison
# 安装图形界面(可选)
sudo apt install unison-gtk
# 安装特定版本(如2.48)
sudo apt install unison=2.48.*
# CentOS/RHEL 7
sudo yum install epel-release
sudo yum install unison
# CentOS/RHEL 8
sudo dnf install epel-release
sudo dnf install unison
# 从源码编译(最新版本)
wget https://github.com/bcpierce00/unison/releases/download/v2.53.0/unison-v2.53.0+ocaml-4.14.0+x86_64.linux.tar.gz
tar -xzf unison*.tar.gz
sudo cp unison /usr/local/bin/
# 使用Homebrew安装
brew install unison
# 或使用MacPorts
sudo port install unison
# 下载Windows安装包
# 从 https://github.com/bcpierce00/unison/releases 下载
# 安装后添加到系统PATH
# 或使用Chocolatey包管理器
choco install unison
Unison使用"档案文件"(archive)来记录同步状态,通过比较档案文件来确定需要同步的文件:
# 工作原理:
1. 比较两个位置的档案文件
2. 检测文件变化(创建、修改、删除)
3. 检测冲突(双方都修改了同一个文件)
4. 应用同步操作
5. 更新档案文件
# 档案文件位置
~/.unison/ # 用户配置文件目录
~/.unison/*.prf # 配置文件
~/.unison/*.archive # 档案文件
# 同步方向术语
- 从A到B(单向)
- 从B到A(单向)
- 双向(默认)
# 基本格式
unison [配置文件] [选项] 目录1 目录2
# 使用配置文件
unison 配置文件名
# 命令行指定目录
unison /path/to/local ssh://user@host//path/to/remote
# 常用简写形式
unison 本地目录 远程目录
unison profile_name
-batch
-auto
-confirm
-testserver
-terse
-silent
-debug all
-logfile sync.log
-repeat 3600
-contactquietly
-path Documents
-ignore "Name *.tmp"
# 1. 基本本地同步(交互式)
unison /home/user/documents /mnt/backup/documents
# 2. 批处理模式(自动同步)
unison /home/user/documents /mnt/backup/documents -batch
# 3. 自动接受非冲突变更
unison /home/user/documents /mnt/backup/documents -auto
# 4. 只同步特定子目录
unison /home/user/documents /mnt/backup/documents -path photos
# 5. 测试同步(不实际执行)
unison /home/user/documents /mnt/backup/documents -dryrun
# 6. 查看同步状态
unison /home/user/documents /mnt/backup/documents -stats
# 1. 通过SSH同步
unison /local/dir ssh://user@remote.example.com//remote/dir
# 2. 指定SSH端口
unison /local/dir ssh://user@remote.example.com:2222//remote/dir
# 3. 使用SSH密钥(无需密码)
unison /local/dir ssh://user@remote.example.com//remote/dir -sshargs "-i /path/to/key"
# 4. 批量模式远程同步
unison /local/dir ssh://user@remote.example.com//remote/dir -batch
# 5. 测试服务器连接
unison -testserver ssh://user@remote.example.com//remote/dir
# 6. 使用RSH协议(不推荐,不安全)
unison /local/dir rsh://user@remote.example.com//remote/dir
配置文件存储在 ~/.unison/ 目录中,用于保存同步配置:
# ~/.unison/mybackup.prf 示例
# 根目录配置
root = /home/user/documents
root = ssh://user@server.example.com//backup/documents
# 同步选项
auto = true
batch = true
confirmbigdeletes = false
log = true
logfile = /var/log/unison/mybackup.log
# 忽略规则
ignore = Name *.tmp
ignore = Name *.log
ignore = Name .DS_Store
ignore = Name .git
ignore = Name .svn
ignore = Path .cache
ignore = Path .tmp
# 路径限制
path = documents
path = photos
path = music
# 冲突处理
prefer = newer # 优先使用较新文件
# prefer = local # 优先使用本地文件
# prefer = remote # 优先使用远程文件
# SSH设置
sshargs = -C -o ServerAliveInterval=30
# 性能优化
maxthreads = 10
retry = 3
contactquietly = true
# 备份设置
backup = Name *.doc
backuplocation = local
backupdir = /home/user/unison-backups
maxbackups = 5
# 使用配置文件同步
unison mybackup
# 查看配置文件
ls -la ~/.unison/*.prf
# 创建默认配置文件
unison -ui text -dumbtty # 交互式创建配置
# 1. 冲突检测示例
# 文件在两端都被修改时产生冲突
unison /local/dir /remote/dir
# 输出类似:
# Conflict: file.txt
# local changed on 2024-01-01 10:00:00
# remote changed on 2024-01-01 11:00:00
# 2. 冲突解决策略
# a) 优先使用较新文件
unison /local/dir /remote/dir -prefer newer
# b) 优先使用本地文件
unison /local/dir /remote/dir -prefer local
# c) 优先使用远程文件
unison /local/dir /remote/dir -prefer remote
# d) 合并文件(需要配置合并工具)
# 在配置文件中添加:
merge = Name *.txt -> diff3 -m CURRENT1 CURRENT2 CURRENTARCH
# 3. 备份冲突文件
# 在配置文件中添加:
backup = Name *
backuplocation = local
backupdir = /path/to/backups
maxbackups = 10
# 4. 交互式冲突解决
unison /local/dir /remote/dir -confirm
# 5. 忽略特定冲突
# 在配置文件中添加:
ignorenot = Name important.txt # 不忽略重要文件
# 1. 同步多个目录
# 创建配置文件 multi.prf
cat > ~/.unison/multi.prf << 'EOF'
# 主目录同步
root = /home/user
root = ssh://user@server//backup/home
# 排除大文件目录
ignore = Path videos
ignore = Path downloads
# 包含重要目录
path = documents
path = pictures
path = .config
# 单独配置音乐目录
include extra/music.prf
EOF
# 2. 创建子配置文件
mkdir -p ~/.unison/extra
cat > ~/.unison/extra/music.prf << 'EOF'
# 音乐目录特殊配置
root = /home/user/music
root = ssh://user@server//backup/music
# 只同步mp3和flac文件
ignore = Name *
include = Name *.mp3
include = Name *.flac
# 保持目录结构
times = true
perms = true
EOF
# 3. 执行同步
unison multi
# 1. 使用cron定时同步
# 编辑crontab
crontab -e
# 添加以下行(每小时同步一次)
0 * * * * /usr/bin/unison -batch /home/user/documents ssh://user@server//backup/documents
# 2. 使用systemd定时服务
# 创建服务文件
sudo vim /etc/systemd/system/unison-sync.service
[Unit]
Description=Unison Document Sync
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=username
ExecStart=/usr/bin/unison -batch documents
Environment=HOME=/home/username
[Install]
WantedBy=multi-user.target
# 创建定时器
sudo vim /etc/systemd/system/unison-sync.timer
[Unit]
Description=Unison Sync Timer
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
# 启用定时器
sudo systemctl enable unison-sync.timer
sudo systemctl start unison-sync.timer
# 3. 使用inotify实时同步(需要unison-fsmonitor)
sudo apt install unison-fsmonitor
unison /local/dir /remote/dir -repeat watch
# 4. 循环同步(每10分钟)
unison /local/dir /remote/dir -repeat 600
#!/bin/bash
# unison_backup.sh - 自动备份脚本
CONFIG_DIR="$HOME/.unison"
LOG_DIR="$HOME/logs/unison"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$LOG_DIR"
# 配置文件列表
profiles=("documents" "photos" "music" "code")
echo "开始同步: $(date)" | tee -a "$LOG_DIR/sync_$DATE.log"
for profile in "${profiles[@]}"; do
echo "同步配置: $profile" | tee -a "$LOG_DIR/sync_$DATE.log"
if [ -f "$CONFIG_DIR/$profile.prf" ]; then
unison "$profile" -batch -logfile "$LOG_DIR/${profile}_$DATE.log" 2>&1 | tee -a "$LOG_DIR/sync_$DATE.log"
if [ $? -eq 0 ]; then
echo " ✓ $profile 同步成功" | tee -a "$LOG_DIR/sync_$DATE.log"
else
echo " ✗ $profile 同步失败" | tee -a "$LOG_DIR/sync_$DATE.log"
fi
else
echo " ! 配置文件 $profile.prf 不存在" | tee -a "$LOG_DIR/sync_$DATE.log"
fi
done
echo "同步完成: $(date)" | tee -a "$LOG_DIR/sync_$DATE.log"
# 发送通知(需要配置邮件或通知服务)
if command -v notify-send &> /dev/null; then
notify-send "Unison同步完成" "所有配置同步执行完毕"
fi
# 1. Linux ↔ Windows 同步
# Windows端安装Unison,配置相同的版本
# 使用Samba共享或SSH连接
# Linux端同步到Windows共享
unison /home/user/documents smb://windows-pc/shared/documents
# 或通过SSH同步到Windows(需安装SSH服务器)
unison /home/user/documents ssh://user@windows-pc//C:/Users/user/documents
# 2. macOS ↔ Linux 同步
# macOS安装:brew install unison
# 忽略macOS特有文件
ignore = Name .DS_Store
ignore = Name ._*
ignore = Name .Spotlight-*
ignore = Name .Trashes
ignore = Name .fseventsd
# 3. 三台机器同步策略
# 使用星型拓扑:A ↔ C, B ↔ C
# C作为中心节点,A和B通过C间接同步
# 4. 版本控制注意事项
# 确保所有机器使用相同版本的Unison
unison -version
# 5. 字符编码处理
# 在配置文件中添加:
charset = utf8
unicode = yes
# 错误: Connection refused
# 解决方案:
# 1. 检查SSH服务
ssh user@server
# 2. 测试Unison连接
unison -testserver ssh://user@server//path
# 3. 检查防火墙
sudo ufw allow 22/tcp
# 4. 使用详细模式
unison -debug ssh ssh://user@server//path
# 错误: Fatal error: Received unexpected header
# 解决方案:
# 1. 检查版本
unison -version
# 2. 安装相同版本
# 在两端安装相同版本的Unison
# 3. 使用-version指定版本
unison -version 2.48
# 4. 从源码编译相同版本
# 下载相同版本的源码编译安装
# 错误: Permission denied
# 解决方案:
# 1. 检查文件权限
ls -la /path/to/sync
# 2. 使用正确的用户
sudo unison /path1 /path2
# 3. 配置权限保留
# 在配置文件中添加:
owner = true
group = true
perms = true
# 4. 忽略权限问题
noperms = true
# 错误: Archive format mismatch
# 解决方案:
# 1. 删除损坏的档案文件
rm ~/.unison/*.archive
# 2. 重新扫描文件
unison /path1 /path2 -force /path1
# 3. 重置同步状态
unison /path1 /path2 -reset
# 4. 创建新的配置文件
cp ~/.unison/default.prf ~/.unison/default.prf.backup
rm ~/.unison/default.prf
# 启用详细调试
unison /path1 /path2 -debug all 2>&1 | tee debug.log
# 启用特定模块调试
unison /path1 /path2 -debug update -debug ssh
# 查看同步统计
unison /path1 /path2 -stats
# 检查配置文件
unison -prefs /path1 /path2
# 查看Unison内部状态
unison /path1 /path2 -dumbtty -ui text
# 清理Unison缓存
rm -rf ~/.unison/*.archive
rm -f ~/.unison/*.log
# 测试配置文件语法
unison -test /path/to/profile.prf
| 特性对比 | unison | rsync | syncthing |
|---|---|---|---|
| 同步方向 | 双向 | 单向(主从) | 双向(P2P) |
| 冲突处理 | 智能检测和解决 | 覆盖(无检测) | 版本控制 |
| 实时同步 | 需要外部监控 | 不支持 | 支持 |
| 跨平台 | 优秀 | 优秀 | 优秀 |
| 安全性 | SSH加密 | SSH加密 | TLS加密 |
| 配置复杂度 | 中等 | 简单 | 中等(Web界面) |
| 适用场景 | 双向同步、多设备文件同步 | 备份、单向同步、镜像 | 实时同步、多设备同步 |
#!/bin/bash
# unison_manager.sh - 管理多设备同步
CONFIG_DIR="$HOME/.unison"
LOG_FILE="$HOME/logs/unison/manager.log"
# 设备列表
declare -A devices=(
["laptop"]="ssh://user@laptop//home/user"
["desktop"]="ssh://user@desktop//home/user"
["server"]="ssh://user@server//backup"
)
# 同步配置
sync_config() {
local config=$1
local device=$2
echo "[$(date)] 同步 $config 到 $device" >> "$LOG_FILE"
unison "$config" -root2 "${devices[$device]}" -batch -logfile "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
echo " ✓ 成功" >> "$LOG_FILE"
else
echo " ✗ 失败" >> "$LOG_FILE"
fi
}
# 主循环
for config in "$CONFIG_DIR"/*.prf; do
config_name=$(basename "$config" .prf)
for device in "${!devices[@]}"; do
sync_config "$config_name" "$device"
done
done
#!/bin/bash
# conflict_report.sh - 生成冲突报告
CONFIG_DIR="$HOME/.unison"
REPORT_DIR="$HOME/reports/unison"
DATE=$(date +%Y%m%d)
mkdir -p "$REPORT_DIR"
generate_report() {
local config=$1
local report_file="$REPORT_DIR/${config}_${DATE}.txt"
echo "=== Unison冲突报告 ===" > "$report_file"
echo "配置: $config" >> "$report_file"
echo "日期: $(date)" >> "$report_file"
echo "=====================" >> "$report_file"
# 运行unison并捕获冲突
unison "$config" -batch -terse 2>&1 | grep -i conflict >> "$report_file"
# 统计冲突数量
conflict_count=$(grep -c "Conflict" "$report_file" 2>/dev/null || echo "0")
if [ "$conflict_count" -gt 0 ]; then
echo "" >> "$report_file"
echo "发现 $conflict_count 个冲突" >> "$report_file"
echo "请手动解决这些冲突" >> "$report_file"
# 发送邮件通知
if command -v mail &> /dev/null; then
mail -s "Unison冲突报告: $config" user@example.com < "$report_file"
fi
fi
}
# 处理所有配置文件
for config_file in "$CONFIG_DIR"/*.prf; do
config_name=$(basename "$config_file" .prf)
generate_report "$config_name"
done