rsync 命令詳解:是什麼、引數含義與同步範例
rsync 是一個檔案同步命令:先比較源和目標,只傳新增和變化的檔案,本機複製和經 SSH 跨伺服器同步都能用。最常用的寫法是 rsync -avh --progress 源目錄/ 目標目錄/,其中 -a 是歸檔模式,等於 -rlptgoD,會保留許可權、時間、屬主和符號連結。
rsync 是 Linux 和類 Unix 系統裡的檔案同步工具,名字一般解釋為 remote sync。它和 cp、scp 最大的不同是“先比較,再傳輸”:預設按檔案大小和修改時間判斷哪些檔案變了,只傳這些檔案;跨網路傳輸時,一個大檔案只改了一部分,也只傳變化的資料塊。所以同一條命令第一次執行是完整複製,之後再執行只補差異,中斷後重新執行就能接著傳。伺服器之間遷移網站、定期備份目錄、把安裝映象同步到各個機房,用的都是它。日常記住一個寫法就夠了:
rsync -avh --progress /var/www/ /data/www/
rsync 是什麼:和 cp、scp 有什麼區別
| 對比項 | cp | scp | rsync |
|---|---|---|---|
| 能否跨機器 | 只能本機 | 經 SSH 傳到或拉自另一台機器 | 本機、經 SSH、連 rsync 守護程序(TCP 873)都可以 |
| 同一條命令再執行一次 | 全部重新複製 | 全部重新傳輸 | 只傳新增和變化的檔案 |
| 傳到一半中斷 | 從頭再來 | 從頭再來 | 重新執行即跳過已完成的檔案;加 --partial 連沒傳完的檔案也能接著傳 |
| 讓目標和源完全一致 | 做不到,源裡刪掉的檔案在目標裡還留著 | 做不到 | --delete 刪除目標裡多出來的檔案 |
| 保留許可權、時間、屬主、符號連結 | 要加 -a |
-p 只保留時間和許可權位 |
-a 一併保留 |
| 先預演再執行 | 不支援 | 不支援 | -n 只列出將要執行的操作 |
| 排除檔案、限速 | 不支援 | -l 可以限速,不能排除 |
--exclude、--bwlimit |
| 依賴 | 系統自帶 | 兩端有 SSH 即可 | 兩端都要安裝 rsync |
兩點容易被忽略:第一次全量複製時,rsync 不會比 scp 快多少,它的優勢在第二次以後;源和目標都在本機時,rsync 不做分塊比對,直接整檔案複製,因為在本機把兩個檔案各讀一遍,比直接複製還慢。另外,rsync 不能在兩台遠端機器之間直接同步,源和目標至少有一端在執行命令的這台機器上。
引數含義對照表
| 引數 | 全稱 | 作用 | 什麼時候用 |
|---|---|---|---|
-a |
--archive |
歸檔模式,等於 -rlptgoD |
幾乎所有同步都加 |
-v |
--verbose |
列出傳輸的檔名,-vv 輸出更多細節 |
想知道傳了哪些檔案 |
-z |
--compress |
傳輸過程中壓縮 | 跨公網傳程式碼、日誌、文字;本機同步或傳壓縮包、圖片、影片時不加 |
-h |
--human-readable |
大小顯示成 K、M、G | 配合 -v、--progress |
--progress |
— | 顯示每個檔案的傳輸進度和速度 | 傳大檔案 |
-P |
— | 等於 --partial --progress,中斷時保留已傳的部分 |
跨網路傳大檔案 |
--info=progress2 |
— | 顯示整體進度,而不是逐個檔案 | 檔案數量很多時(3.1 版起支援) |
--delete |
— | 刪除目標中有、源中沒有的檔案 | 做映象;先用 -n 預演 |
-n |
--dry-run |
只演練,不做任何修改 | 第一次執行、帶 --delete 時 |
-i |
--itemize-changes |
逐個列出檔案以及變化的原因 | 配合 -n 檢查差異 |
-c |
--checksum |
按校驗和判斷檔案是否相同,而不是大小和時間 | 懷疑時間戳不可靠時;要讀完所有檔案,很慢 |
-u |
--update |
目標裡比源更新的檔案不覆蓋 | 防止覆蓋對方的新修改 |
-e |
--rsh |
指定遠端 shell,如 -e 'ssh -p 22022' |
SSH 連接埠不是 22 時 |
--exclude |
— | 排除匹配的檔案或目錄 | 跳過快取、日誌、.git |
--bwlimit |
— | 限制傳輸速率,預設單位 KiB/s | 白天同步,避免擠佔業務頻寬 |
常見組合這樣讀:rsync -avz 是歸檔、列出檔案、壓縮傳輸,適合跨網路推拉;rsync -ah --progress 是歸檔、大小按 K/M/G 顯示、帶進度,適合本機複製大檔案;rsync -aHAX --numeric-ids 用於整機遷移和系統備份。
rsync -a 是什麼意思:等於 -rlptgoD
| 字母 | 全稱 | 保留或處理什麼 |
|---|---|---|
-r |
--recursive |
遞迴進入子目錄 |
-l |
--links |
符號連結按連結本身複製,不復制它指向的檔案 |
-p |
--perms |
許可權位(讀、寫、執行) |
-t |
--times |
修改時間;不保留的話,下次同步時所有檔案都會因為時間不同被重新處理 |
-g |
--group |
屬組 |
-o |
--owner |
屬主,接收端以 root 執行時才生效 |
-D |
--devices --specials |
裝置檔案,以及命名管道、套接字等特殊檔案 |
-a 不包含三項:-H(硬連結,不加的話硬連結會被複製成多個獨立檔案,佔用成倍的空間)、-A(ACL)、-X(擴充套件屬性,SELinux 的安全標籤就存在這裡)。遷移整機、備份系統目錄時寫成 -aHAX,再加 --numeric-ids 按原始的 UID、GID 數字儲存屬主,不按使用者名稱轉換,備份機上沒有這些使用者也不受影響,將來恢復回原系統時屬主完全一致。
三類命令範例:本地、推送、拉取
遠端路徑的寫法是 使用者@主機:路徑,冒號前是主機,冒號後是那台機器上的路徑。寫在左邊的是源,右邊的是目標,誰在前決定了是推送還是拉取。
本地同步
# 把網站目錄複製到新掛載的資料盤,顯示每個檔案的進度
rsync -ah --progress /var/www/ /data/www/
# 把 /etc 備份到另一塊盤上的日期目錄,保留硬連結、ACL 和擴充套件屬性
rsync -aHAX --info=progress2 /etc/ /backup/etc-$(date +%F)/
推送到遠端伺服器
# 把釋出目錄推到應用伺服器,排除 .git 目錄和日誌檔案
rsync -avz --exclude '.git/' --exclude '*.log' /opt/release/shop/ [email protected]:/opt/shop/
# 對方的 SSH 連接埠改成了 22022,並指定私鑰
rsync -avz -e 'ssh -p 22022 -i ~/.ssh/idc_ed25519' /opt/release/shop/ [email protected]:/opt/shop/
# 白天同步 ISO 映象目錄:限速約 20 MiB/s,中斷後保留已傳部分
rsync -avP --bwlimit=20480 /data/iso/ [email protected]:/data/iso/
從遠端伺服器拉取
# 把 web01 的 Nginx 日誌拉回本機
rsync -avz [email protected]:/var/log/nginx/ /srv/logs/web01/
# 遠端用普通使用者登入,讀 /etc 需要 sudo(該使用者要能免密執行 sudo rsync)
rsync -avz --rsync-path='sudo rsync' [email protected]:/etc/ /srv/backup/web01-etc/
連線 rsync 守護程序
路徑寫成 rsync://主機/模組/ 或 主機::模組 時,rsync 不走 SSH,而是直接連對方 TCP 873 連接埠上的 rsync 服務,多用於公開的軟體映象站:
rsync -av --delete rsync://mirror.example.com/rocky/9/isos/x86_64/ /data/mirror/rocky9-iso/
守護程序方式預設不加密,自己搭建時只在內網開放,不要把可寫的模組暴露到公網。2025 年 1 月釋出的 rsync 3.4.0 修復了多個可被遠端利用的漏洞(如 CVE-2024-12084),對外提供 rsync 服務的機器要確認已經修復:自己編譯安裝的,看 rsync --version 第一行的版本號;用發行版軟體包的,修復通常移植在原來的版本號上,以發行版的安全公告為準。
末尾斜槓的坑:差一個字元,結果完全不同
規則只看源路徑:源以 / 結尾,表示“這個目錄裡面的內容”;不以 / 結尾,表示“這個目錄本身”。目標路徑末尾有沒有斜槓,基本不影響結果。
| 命令 | 執行後的結果 |
|---|---|
rsync -a /var/www /data/ |
得到 /data/www/index.html,多出一層 www |
rsync -a /var/www/ /data/ |
得到 /data/index.html,www 裡的內容直接鋪在 /data 下 |
rsync -a /var/www/ /data/www |
得到 /data/www/index.html;/data/www 不存在時會自動建立 |
rsync -a /var/www /data/www/ |
得到 /data/www/www/index.html,常見的誤操作 |
最危險的是斜槓寫錯又帶著 --delete。本想同步到 /data/www,結果寫成 rsync -a --delete /var/www/ /data/,rsync 會讓整個 /data 和 /var/www 保持一致,/data 下其他目錄被全部刪除。帶 --delete 的命令,目標路徑一定寫到具體的那一級目錄,執行前先加 -n 看一遍。
另外兩個相關細節:rsync 只會自動建立目標路徑的最後一級目錄,上級目錄不存在時會報錯,要先建好,或在 3.2.3 及以後的版本里加 --mkpath;--exclude 的匹配也和斜槓有關,--exclude 'cache/' 排除任何一層名叫 cache 的目錄,--exclude '/cache/' 只排除傳輸根目錄下的那一個,而“根目錄”指的是源路徑末尾斜槓所表示的那一層。
加 –delete 之前:用 -n 預演,讀懂 -i 的輸出
-n 加上 -i,rsync 會把將要做的每一個操作列出來,但不實際執行:
rsync -ani --delete /opt/release/shop/ [email protected]:/opt/shop/
*deleting static/old.js
.d..t...... conf/
<f.st...... conf/app.yml
<f+++++++++ static/new.js
cd+++++++++ uploads/2026/
cL+++++++++ current -> releases/v2
每行開頭是 11 個字元的變化標記,後面是檔名:
| 位置 | 字元 | 含義 |
|---|---|---|
| 第 1 位 | < |
檔案將傳送到遠端(推送時) |
| 第 1 位 | > |
檔案將接收到本機(拉取或本機複製時) |
| 第 1 位 | c |
在目標端新建目錄、符號連結等 |
| 第 1 位 | . |
內容不用傳,只更新屬性 |
| 第 1 位 | * |
附帶一條訊息,最常見的是 *deleting,表示將被刪除 |
| 第 2 位 | f、d、L |
普通檔案、目錄、符號連結 |
| 第 3 到 11 位 | +++++++++ |
新建的專案 |
| 第 4、5 位 | s、t |
大小不同、修改時間不同 |
| 第 6 到 8 位 | p、o、g |
許可權、屬主、屬組不同 |
讀輸出時重點看兩類:*deleting 的行是不是都在預期之內;如果大量檔案只顯示 t(大小相同、時間不同),多半是目標當初複製時沒有保留時間戳,這一輪同步會把時間對齊,之後就不會重複處理了。確認無誤,去掉 -n 正式執行。
常見報錯與退出碼
| 報錯 | 退出碼 | 原因與處理 |
|---|---|---|
bash: rsync: command not found,接著是 connection unexpectedly closed (0 bytes received so far) |
127(較老版本為 12) | 遠端沒有安裝 rsync,用 dnf install rsync 或 apt install rsync 裝上 |
Permission denied (publickey,password) |
255 | SSH 本身沒有連上;先用相同的連接埠和使用者執行 ssh -p 連接埠 使用者@主機 測通 |
send_files failed to open "…": Permission denied (13) |
23 | 傳送端讀不了原始檔;換 root 執行,或用 --rsync-path='sudo rsync' |
chown "…" failed: Operation not permitted (1) |
23 | 目標在不允許改屬主的位置,如開啟了 root_squash 的 NFS、SMB/CIFS 掛載或 exFAT 盤;加 --no-owner --no-group |
file has vanished: "…" |
24 | 同步過程中原始檔被刪除,日誌、快取目錄常見,一般可以忽略 |
中途出現 connection unexpectedly closed 或超時 |
12、30 | 網路中斷或長時間無資料;加 --timeout=300 和 -P 後重新執行 |
寫進指令碼時,退出碼 0 是完全成功,24 通常也可以視為成功,其餘都要告警:
rsync -a --delete /var/www/ [email protected]:/backup/www/
rc=$?
if [ "$rc" -ne 0 ] && [ "$rc" -ne 24 ]; then
echo "rsync 失敗,退出碼 $rc" >&2
exit "$rc"
fi
重灌、遷移之前,先把資料同步出去
在 IDC 場景裡,rsync 用得最多的時刻,是伺服器要重灌系統、換機器或換機房之前。做法是分兩輪:第一輪在業務執行時做全量同步,耗時長也不影響業務;第二輪停掉寫入後再執行一次帶 --delete 的同步,只補差異,停機時間就從“複製全部資料”縮短到“複製最後的改動”。
系統已經啟動不了時,資料同樣能救出來。客戶自己就能在客戶自助端把伺服器切到救援模式,救援系統是臨時啟動的,不動硬碟上的資料,把資料分割槽掛載上來後,用 rsync 推到備份伺服器。救援系統裡如果沒有 rsync,可以從備份伺服器一側用 tar 經 SSH 拉取,兩端都不需要 rsync:
ssh [email protected] 'tar -C /mnt/data -cf - .' | tar -C /backup/web01 -xf -
這種方式沒有增量和斷點續傳,中斷了只能整體重來,適合資料量不大的時候應急使用。
常見問題
rsync 能做雙向同步嗎?
不能。rsync 每次只有一個方向,源覆蓋目標;兩邊都會改的目錄,來回執行 rsync 會讓一方的修改被另一方覆蓋。需要雙向同步時,用 Unison、Syncthing 這類專門的工具。
Windows 上能用 rsync 嗎?
Windows 沒有原生的 rsync。常見做法是在 WSL 裡使用 Linux 發行版自帶的 rsync,以 /mnt/c/ 這樣的路徑存取 Windows 磁碟;也有基於 Cygwin 的 cwRsync。只是偶爾在 Windows 和 Linux 之間傳檔案的話,scp 或 SFTP 客戶端更省事。
怎麼讓 rsync 定時自動執行?
先配好 SSH 金鑰登入,再寫進 crontab,例如每天 3 點執行:0 3 * * * flock -n /tmp/sync-www.lock rsync -a /var/www/ [email protected]:/backup/www/ >> /var/log/sync-www.log 2>&1。flock -n 保證上一輪還沒跑完時,這一輪直接跳過,不會兩個同步任務疊在一起。