Linux命令-rsync(远程/本地文件同步 —— 增量传输的备份与镜像神器)

# Linux命令-rsync(远程/本地文件同步 ------ 增量传输的备份与镜像神器)

    • [🔰 简介](#🔰 简介)
    • [📖 语法](#📖 语法)
    • [⚙️ 选项](#⚙️ 选项)
    • [💡 示例](#💡 示例)
      • [示例 1:本地目录同步(基本用法)](#示例 1:本地目录同步(基本用法))
      • [示例 2:推送到远程服务器](#示例 2:推送到远程服务器)
      • [示例 3:从远程拉取到本地](#示例 3:从远程拉取到本地)
      • [示例 4:镜像同步(删除目标多余文件)](#示例 4:镜像同步(删除目标多余文件))
      • [示例 5:文件过滤与排除](#示例 5:文件过滤与排除)
      • [示例 6:限速与断点续传](#示例 6:限速与断点续传)
      • [示例 7:实际运维场景集合](#示例 7:实际运维场景集合)
    • [⚠️ 注意](#⚠️ 注意)
      • [源路径末尾 `/` 的含义(极易混淆!)](#源路径末尾 / 的含义(极易混淆!))
      • [rsync vs scp vs cp 对比](#rsync vs scp vs cp 对比)
      • 常见陷阱与排查
    • [📝 总结](#📝 总结)
    • [📚 相关命令](#📚 相关命令)

快速参考rsync 是 Linux 系统中最强大的文件同步和传输工具。它采用独有的增量传输算法------只传输源和目标之间的差异部分,极大节省带宽和时间。支持本地同步、远程推送/拉取、SSH 隧道传输、daemon 模式,并具备断点续传、文件过滤、带宽限制、删除多余文件等生产级特性。是系统备份、文件分发、网站部署、数据迁移的首选工具。


🔰 简介

rsync 由 Andrew Tridgell 和 Paul Mackerras 开发,其核心创新在于 "rsync 算法":将文件分块,计算每块的校验和,只传输源端和目标端不同的块。这意味着对一个 10GB 文件,即使只改动了最后 1KB,也只传输那 1KB。

六种使用模式

模式 语法 说明
本地到本地 rsync [选项] 源 目标 同主机内目录/文件同步
本地到远程 rsync [选项] 源 用户@主机:目标 Push:推送文件到远程
远程到本地 rsync [选项] 用户@主机:源 目标 Pull:从远程拉取文件
远程到远程 rsync [选项] 用户@主机A:源 用户@主机B:目标 通过本地中转
Daemon 模式 rsync [选项] 用户@主机::模块/路径 直接连接 rsync 服务
SSH 隧道 rsync [选项] -e ssh 源 目标 通过 SSH 加密传输

安装位置

bash 复制代码
# 查看 rsync 路径和版本
which rsync
# 输出:/usr/bin/rsync

rsync --version | head -3
# 输出:
# rsync  version 3.1.2  protocol version 31
# Copyright (C) 1996-2015 by Andrew Tridgell, Wayne Davison, and others.
# Web site: http://rsync.samba.org/

# 安装(大多数发行版默认安装)
# CentOS/RHEL
sudo yum install rsync

# CentOS/RHEL 8+
sudo dnf install rsync

# Debian/Ubuntu
sudo apt install rsync

# 查看配置文件路径
ls /etc/rsyncd.conf 2>/dev/null || echo "daemon 模式配置文件不存在(需手动创建)"

📖 语法

复制代码
rsync [选项] 源 目标

源和目标格式:

格式 说明
/path/to/dir 本地路径
user@host:/path 远程路径(SSH 方式)
user@host::module/path 远程路径(daemon 方式)
rsync://user@host/module/path URL 格式(daemon 方式)
[USER@]HOST::SRC [USER@]HOST::DEST 远程到远程(本地中转)

⚙️ 选项

核心选项(必须掌握)

选项 说明
-a, --archive 归档模式(最常用!) 等价于 -rlptgoD
-v, --verbose 详细输出
-z, --compress 传输时压缩数据
-P 等价于 --partial --progress(断点续传 + 进度)
-h, --human-readable 人类可读的大小格式(如 1.5GB)
-n, --dry-run 模拟运行(预览将要进行的操作,不实际传输)

-a 归档模式的分解

子选项 说明
-r, --recursive 递归目录
-l, --links 保留符号链接
-p, --perms 保留权限
-t, --times 保留修改时间
-g, --group 保留组
-o, --owner 保留所有者(需 root)
-D 等价于 --devices --specials(保留设备文件和特殊文件)

高级选项

选项 说明
--delete ⚠️ 小心使用 删除目标端多余的文件(镜像同步)
--delete-excluded 同时删除被排除的文件
--delete-before 传输前先删除(节省目标空间)
--exclude 模式 排除匹配的文件/目录
--exclude-from 文件 从文件读取排除模式列表
--include 模式 包含匹配的文件/目录
--bwlimit 速率 限制传输带宽(单位 KB/s,如 --bwlimit=10000 即 10MB/s)
-e, --rsh 命令 指定远程 Shell(如 -e "ssh -p 2222"
--partial 保留未完整传输的文件(断点续传基础)
--progress 显示传输进度
--stats 传输完成后显示统计信息
-x, --one-file-system 不跨越文件系统边界
-u, --update 跳过目标端更新的文件
--max-size 大小 限制最大文件大小
--min-size 大小 限制最小文件大小
--remove-source-files 传输成功后删除源文件(相当于移动)
--chmod 权限 设置目标文件权限(如 --chmod=D0755,F0644
--log-file 文件 将输出记录到日志文件

💡 示例

示例 1:本地目录同步(基本用法)

bash 复制代码
# 准备工作:创建测试目录和文件
mkdir -p /tmp/rsync_test/source
cd /tmp/rsync_test/source
mkdir -p dir1 dir2 dir3
echo "Hello from file1" > file1.txt
echo "Hello from file2" > file2.txt
echo "Hello from file3" > dir1/file3.txt
echo "Config data" > config.conf

# 查看源目录结构
find /tmp/rsync_test/source -type f
# 输出:
# /tmp/rsync_test/source/file1.txt
# /tmp/rsync_test/source/file2.txt
# /tmp/rsync_test/source/config.conf
# /tmp/rsync_test/source/dir1/file3.txt

# 基本同步(保留目录结构、权限、时间戳)
rsync -av /tmp/rsync_test/source/ /tmp/rsync_test/dest/
# 输出:
# sending incremental file list
# ./
# config.conf
# file1.txt
# file2.txt
# dir1/
# dir1/file3.txt
# dir2/
# dir3/
#
# sent 558 bytes  received 124 bytes  1,364.00 bytes/sec
# total size is 58  speedup is 0.09

# 验证目标目录
ls -la /tmp/rsync_test/dest/
# 输出:
# drwxr-xr-x  5 user group  100 Jun 14 14:30 .
# drwxr-xr-x  4 user group   80 Jun 14 14:30 ..
# -rw-r--r--  1 user group   13 Jun 14 14:30 config.conf
# drwxr-xr-x  2 user group   40 Jun 14 14:30 dir1
# drwxr-xr-x  2 user group   40 Jun 14 14:30 dir2
# drwxr-xr-x  2 user group   40 Jun 14 14:30 dir3
# -rw-r--r--  1 user group   18 Jun 14 14:30 file1.txt
# -rw-r--r--  1 user group   18 Jun 14 14:30 file2.txt

示例 2:推送到远程服务器

bash 复制代码
# 将本地 /data/web/ 推送到远程服务器的 /var/www/
rsync -avz /data/web/ user@web-server:/var/www/
# 输出:
# sending incremental file list
# ./
# index.html
# style.css
# script.js
# images/
# images/logo.png
# images/banner.jpg
#
# sent 2,456,789 bytes  received 156 bytes  491,389.00 bytes/sec
# total size is 2,450,000  speedup is 1.00

# 带进度条的推送(推荐日常使用)
rsync -avzP /data/web/ user@web-server:/var/www/
# 输出:
# sending incremental file list
# ./
# index.html
#          3,456 100%    0.00kB/s    0:00:00 (xfr#1, to-chk=4/6)
# style.css
#         12,789 100%   12.49MB/s    0:00:00 (xfr#2, to-chk=3/6)
# script.js
#         45,678 100%   22.30MB/s    0:00:00 (xfr#3, to-chk=2/6)
# images/logo.png
#        234,567 100%   19.12MB/s    0:00:00 (xfr#4, to-chk=1/6)
# images/banner.jpg
#      2,160,345 100%   17.85MB/s    0:00:00 (xfr#5, to-chk=0/6)
#
# sent 2,458,912 bytes  received 115 bytes  4,918,054.00 bytes/sec
# total size is 2,450,000  speedup is 1.00

# 测试大文件增量同步(第二次传输几乎瞬间完成)
rsync -avh --stats /data/web/ user@web-server:/var/www/
# 输出:
# sending incremental file list
#
# Number of files: 6 (reg: 5, dir: 1)
# Number of created files: 0
# Number of deleted files: 0
# Number of regular files transferred: 0      # 没有文件被传输!
# Total file size: 2.39M bytes
# Total transferred file size: 0 bytes        # 传输了 0 字节!
# Literal data: 0 bytes
# Matched data: 0 bytes
# File list size: 0
# File list generation time: 0.001 seconds
# File list transfer time: 0.000 seconds
# Total bytes sent: 205
# Total bytes received: 108
#
# sent 205 bytes  received 108 bytes  626.00 bytes/sec
# total size is 2,450,000  speedup is 7,827.48

示例 3:从远程拉取到本地

bash 复制代码
# 从远程服务器拉取数据
rsync -avz user@db-server:/var/backups/ /local/backups/
# 输出:
# receiving incremental file list
# ./
# db_backup_20260601.sql.gz
# db_backup_20260602.sql.gz
# db_backup_20260603.sql.gz
#
# sent 45 bytes  received 125,678,901 bytes  8,378,596.40 bytes/sec
# total size is 125,600,000  speedup is 1.00

# 拉取并显示进度
rsync -avzP user@db-server:/var/backups/db_backup_20260614.sql.gz /local/backups/
# 输出:
# receiving incremental file list
# db_backup_20260614.sql.gz
#  125,678,901 100%   35.67MB/s    0:00:03 (xfr#1, to-chk=0/1)
#
# sent 30 bytes  received 125,722,456 bytes  25,144,497.20 bytes/sec
# total size is 125,600,000  speedup is 1.00

# 通过非标准 SSH 端口拉取
rsync -avz -e "ssh -p 2222" user@db-server:/data/ /local/data/

示例 4:镜像同步(删除目标多余文件)

bash 复制代码
# 准备工作:目标端有多余文件
mkdir -p /tmp/rsync_mirror/src /tmp/rsync_mirror/dst
echo "keep" > /tmp/rsync_mirror/src/keep.txt
echo "remove me" > /tmp/rsync_mirror/dst/old_file.txt
echo "keep" > /tmp/rsync_mirror/dst/keep.txt

# 查看同步前状态
ls -la /tmp/rsync_mirror/src/
# 输出:keep.txt
ls -la /tmp/rsync_mirror/dst/
# 输出:keep.txt  old_file.txt

# 预览镜像同步效果(--dry-run 模拟)
rsync -av --delete --dry-run /tmp/rsync_mirror/src/ /tmp/rsync_mirror/dst/
# 输出:
# sending incremental file list
# deleting old_file.txt          # 会删除!
# ./
#
# sent 105 bytes  received 13 bytes  236.00 bytes/sec

# 执行镜像同步
rsync -av --delete /tmp/rsync_mirror/src/ /tmp/rsync_mirror/dst/
# 输出:
# sending incremental file list
# deleting old_file.txt
# ./
#
# sent 110 bytes  received 15 bytes  250.00 bytes/sec

# 验证
ls -la /tmp/rsync_mirror/dst/
# 输出:keep.txt(old_file.txt 已被删除)
# ⚠️ 目标端与源端完全一致!

# 生产环境中使用前务必先 --dry-run
rsync -avz --delete --dry-run /production/data/ backup-server:/backup/data/
# 确认无误后再执行
rsync -avz --delete /production/data/ backup-server:/backup/data/

示例 5:文件过滤与排除

bash 复制代码
# 准备工作
mkdir -p /tmp/rsync_filter/project
cd /tmp/rsync_filter/project
mkdir -p src dist node_modules .git logs
echo "source" > src/app.js
echo "build" > dist/bundle.js
echo "modules" > node_modules/module.js
echo "git" > .git/HEAD
echo "log" > logs/app.log
echo "log" > logs/error.log
touch README.md package.json

# 排除 node_modules 和 .git 目录
rsync -av --exclude='node_modules/' --exclude='.git/' /tmp/rsync_filter/project/ /tmp/rsync_filter/backup/
# 输出(注意 node_modules 和 .git 未出现):
# sending incremental file list
# ./
# README.md
# package.json
# dist/
# dist/bundle.js
# logs/
# logs/app.log
# logs/error.log
# src/
# src/app.js
#
# sent 456 bytes  received 78 bytes  1,068.00 bytes/sec

# 排除所有 .log 文件
rsync -av --exclude='*.log' /tmp/rsync_filter/project/ /tmp/rsync_filter/backup2/
# 输出(无 log 文件):
# ./
# README.md
# package.json
# dist/
# dist/bundle.js
# src/
# src/app.js

# 使用排除文件列表(适合复杂过滤规则)
cat > /tmp/rsync_exclude.txt << 'EOF'
node_modules/
.git/
*.log
dist/
.DS_Store
Thumbs.db
*.swp
*~
EOF

rsync -av --exclude-from=/tmp/rsync_exclude.txt \
  /tmp/rsync_filter/project/ /tmp/rsync_filter/backup3/
# 输出:
# ./
# README.md
# package.json
# src/
# src/app.js

示例 6:限速与断点续传

bash 复制代码
# 限速 10MB/s(防止占满带宽影响其他服务)
rsync -avzP --bwlimit=10000 /data/large_files/ user@remote:/backup/
# 输出:
# large_file.tar.gz
#  2,147,483,648  10%   10.00MB/s    0:03:12 (xfr#1, to-chk=3/4)
#                               ^^^^^^^^^^^^ 稳定在 10MB/s

# 断点续传:中断后使用相同命令继续
# 第一次传输(模拟中断)
rsync -avP /data/huge_file.iso user@remote:/backup/
# huge_file.iso
#  4,294,967,296  45%   50.00MB/s    0:00:38
# ^C  (用户中断:Ctrl+C)

# 重新执行相同命令(自动续传)
rsync -avP /data/huge_file.iso user@remote:/backup/
# huge_file.iso
#  4,294,967,296  45%   50.00MB/s    0:00:38
#  (从 45% 继续,而非从 0% 开始!)

# 限速 + 非高峰时段打包传输(脚本示例)
cat > /usr/local/bin/nightly-sync.sh << 'SCRIPT'
#!/bin/bash
# 夜间备份脚本:限速 50MB/s,记录日志
rsync -avzP \
  --bwlimit=50000 \
  --log-file=/var/log/rsync-backup.log \
  --exclude='*.tmp' \
  --exclude='.cache/' \
  /data/production/ \
  backup-server:/nightly-backup/$(date +%Y%m%d)/
echo "$(date): Sync completed with exit code $?" >> /var/log/rsync-backup.log
SCRIPT
chmod +x /usr/local/bin/nightly-sync.sh

示例 7:实际运维场景集合

bash 复制代码
# === 场景1:网站代码部署 ===
rsync -avz --delete \
  --exclude='.git/' \
  --exclude='.env' \
  --exclude='storage/' \
  /local/project/ \
  deploy@web-server:/var/www/project/
# 输出:
# sending incremental file list
# deleting old-page.html
# ./
# app/Controllers/NewController.php
# resources/views/
# resources/views/welcome.blade.php

# === 场景2:数据库备份同步 ===
rsync -avzP --remove-source-files \
  /tmp/daily_backups/ \
  archive@nas-server:/archive/db/$(date +%Y/%m)/
# --remove-source-files 传输成功后删除本地文件(相当于移动)

# === 场景3:Linux 系统迁移 ===
# 将整个系统复制到新磁盘(排除虚拟文件系统)
sudo rsync -avxHAX --progress \
  --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} \
  / /mnt/new_disk/
# -x: 不跨文件系统
# -H: 保留硬链接
# -A: 保留 ACL
# -X: 保留扩展属性

# === 场景4:跨服务器目录对比 ===
# 使用 --dry-run 查看差异而不实际同步
rsync -avz --dry-run --itemize-changes \
  /data/server_a/ user@server_b:/data/server_a/
# 输出:
# >f+++++++++ new_file.txt        # > 表示发送到远程
# .d..t...... existing_dir/        # . 表示未传输(仅属性变化)
# >f.st...... modified_file.txt   # s 大小变化,t 时间变化

# === 场景5:使用 daemon 模式 ===
# 服务端 /etc/rsyncd.conf 配置示例
cat > /tmp/rsyncd_example.conf << 'EOF'
uid = nobody
gid = nobody
use chroot = yes
max connections = 10
timeout = 300

[backup]
    path = /data/backup
    comment = Backup Area
    read only = no
    list = yes
    auth users = backupuser
    secrets file = /etc/rsyncd.secrets

[public]
    path = /data/public
    comment = Public Files
    read only = yes
    list = yes
EOF

# 客户端使用 daemon 模式拉取
rsync -av rsync://backupuser@nas-server/backup/ /local/backup/
# 或双冒号语法
rsync -av backupuser@nas-server::backup/ /local/backup/

⚠️ 注意

源路径末尾 / 的含义(极易混淆!)

bash 复制代码
# 准备测试环境
mkdir -p /tmp/slash_test/src/data
touch /tmp/slash_test/src/data/file.txt

# === 不带末尾 /(同步目录本身)===
rsync -av /tmp/slash_test/src /tmp/slash_test/dest1/
# 结果:
find /tmp/slash_test/dest1 -type f
# 输出:/tmp/slash_test/dest1/src/data/file.txt
#       创建了 src 目录本身!

# === 带末尾 /(同步目录内容)===
rsync -av /tmp/slash_test/src/ /tmp/slash_test/dest2/
# 结果:
find /tmp/slash_test/dest2 -type f
# 输出:/tmp/slash_test/dest2/data/file.txt
#       只同步了内容,没有创建 src 目录!

# 记忆口诀:
# /src  → 目标中创建 src/(复制这个目录)
# /src/ → 目标中展开 src 的内容(不创建 src 目录本身)

rsync vs scp vs cp 对比

bash 复制代码
# === scp(安全复制)===
# 适用:简单的一次性文件传输
# 缺点:总是全量传输,不支持增量
scp -r /data/ user@server:/data/
# 输出:逐个文件复制,不检查已有文件

# === cp(本地复制)===
# 适用:本地简单复制
# 缺点:无增量、无远程、无过滤
cp -a /src/ /dst/

# === rsync(智能同步)===
# 适用:备份、镜像、部署、增量传输
# 优势:
#   1. 增量传输(只传差异)
#   2. 断点续传
#   3. 文件过滤
#   4. 删除同步
#   5. 带宽限制
#   6. 支持多种传输协议

# 性能对比示例
# scp:传输修改了 1KB 的 100GB 文件 → 传输 100GB(需要几个小时)
# rsync:传输修改了 1KB 的 100GB 文件 → 传输 ~1KB(几乎瞬间完成)

常见陷阱与排查

bash 复制代码
# 陷阱1:源路径缺少末尾 / 导致目录嵌套
# 错误:
rsync -av /source dest-server:/backup/
# 结果:/backup/source/...(创建了额外的 source 目录)

# 陷阱2:--delete 误删重要文件
# 始终先用 --dry-run 预览!
rsync -av --delete --dry-run /src/ dest-server:/dst/
# 检查输出的 "deleting ..." 行,确认无误后再去掉 --dry-run

# 陷阱3:权限问题
# 传输到 root 拥有的目录时可能出错
sudo rsync -av --rsync-path="sudo rsync" /src/ user@server:/root/dst/

# 陷阱4:大文件传输中断
# 使用 -P 确保支持断点续传
rsync -avP /large/file user@server:/path/

# 陷阱5:符号链接问题
# -a 已包含 -l(保留符号链接),但如果需要复制实际文件:
rsync -avL --copy-links /src/ /dst/   # -L 跟随并复制链接目标

📝 总结

rsync 是 Linux 运维工具箱中最重要的传输工具之一:

  • 核心优势:增量传输 ------ 只传输差异部分,第二次同步几乎瞬间完成
  • 归档模式 -a 是日常使用的基础选项,保留所有属性
  • -P(进度 + 断点续传)在大文件或网络不稳定时至关重要
  • --delete 实现镜像同步,但务必先用 --dry-run 预览
  • 路径末尾 / 决定是同步目录本身还是目录内容,易混淆但极关键
  • 六种模式涵盖了从本地复制到远程 daemon 的所有场景

掌握了 rsync,就掌握了 Linux 下最高效的数据传输方式。


📚 相关命令

命令 说明
scp 基于 SSH 的简单安全文件复制(全量)
cp 本地文件复制
mv 移动/重命名文件
tar 归档工具(常与 rsync 配合备份)
ssh rsync 远程传输的底层隧道
cron 定时任务(配合 rsync 实现周期性备份)
lsyncd 基于 rsync + inotify 的实时同步工具
rclone 云存储同步工具(rsync 的云版本)
相关推荐
爆浇牛肉面1 小时前
Linux进阶命令:测开必学的curl和jq
linux
Sinclair2 小时前
安企CMS的安装-常见安装问题排查
运维·后端
Sinclair2 小时前
安企CMS的安装-安装引导与初始化
运维·后端
Sinclair2 小时前
安企CMS的安装-源码编译安装
运维·后端·go
Sinclair2 小时前
安企CMS的安装-同一服务器多站点部署
运维·后端
Sinclair2 小时前
安企CMS的安装-Docker 部署
运维·docker·容器
Sinclair2 小时前
安企CMS的安装-服务器手动部署
运维·后端
shujudang2 小时前
业务闭环视角下的营销自动化(MA)平台选型逻辑
大数据·运维·数据分析·自动化·营销自动化
Sinclair2 小时前
安企CMS的安装-宝塔面板部署
服务器·后端