提要php
-
熟悉 rsync 的功能及其特色
-
掌握 rsync 語法及經常使用選項的功能
-
掌握 rsync 命令的三種基本使用方法
-
掌握如何篩選 rsync 的傳輸目標
-
掌握使用 rsync 進行鏡像和增量備份的方法
rsync 簡介
rsync(remote synchronize)是一個遠程數據同步工具,可經過 LAN/WAN 快速同步多臺主機之間的文件。也可使用 rsync 同步本地硬盤中的不一樣目錄。
rsync 是用於替代 rcp 的一個工具,rsync 使用所謂的 rsync算法 進行數據同步,這種算法只傳送兩個文件的不一樣部分,而不是每次都整份傳送,所以速度至關快。 您能夠參考 How Rsync Works A Practical Overview 進一步瞭解 rsync 的運做機制。
rsync 的初始做者是 Andrew Tridgell 和 Paul Mackerras,目前由 http://rsync.samba.org 維護。
rsync 支持大多數的類 Unix 系統,不管是 Linux、Solaris 仍是 BSD上 都通過了良好的測試。 CentOS系統默認就安裝了 rsync 軟件包。 此外,在 windows 平臺下也有相應的版本,如 cwrsync 和DeltaCopy 等。
rsync 具備以下的基本特性:html
-
能夠鏡像保存整個目錄樹和文件系統
-
能夠很容易作到保持原來文件的權限、時間、軟硬連接等
-
無須特殊權限便可安裝
-
優化的流程,文件傳輸效率高
-
可使用 rsh、ssh 方式來傳輸文件,固然也能夠經過直接的 socket 鏈接
-
支持匿名傳輸,以方便進行網站鏡象
在使用 rsync 進行遠程同步時,可使用兩種方式:遠程 Shell 方式(建議使用 ssh,用戶驗證由 ssh 負責)和 C/S 方式(即客戶鏈接遠程 rsync 服務器,用戶驗證由 rsync 服務器負責)。
不管本地同步目錄仍是遠程同步數據,首次運行時將會把所有文件拷貝一次,之後再運行時將只拷貝有變化的文件(對於新文件)或文件的變化部分(對於原有文件)。
本節重點介紹 rsync 客戶命令的使用,有關 rsync 服務器的配置和使用請參見下節。
rsync 在首次複製時沒有速度優點,速度不如 tar,所以當數據量很大時您能夠考慮先使用 tar 進行首次複製,而後再使用 rsync 進行數據同步。node
鏡像、備份和歸檔
實施備份的兩種狀況:linux
-
需保留備份歷史歸檔:在備份時保留歷史的備份歸檔,是爲了在系統出現錯誤後能恢復到從前正確的狀態。這可使用徹底備份和增量備份來完成。
-
可使用 tar 命令保存歸檔文件。
-
爲了提升備份效率,也可使用 rsync 結合 tar 來完成。
-
-
無需保留備份歷史歸檔:若無需從歷史備份恢復到正確狀態,則只備份系統最「新鮮」的狀態便可。這能夠簡單地使用 rsync 同步來完成。此時一般稱爲鏡像。鏡像能夠分爲兩種:
-
被鏡像的目錄在各個主機上保持相同的位置。此時通常是爲了實施負載均衡而對多個主機進行同步鏡像。例如:將主機 A 的 /srv/www 目錄同步到主機 B 的 /srv/www 目錄等。
-
被鏡像的目錄在各個主機上不保持相同的位置。例如:主機 A 和主機 B 都運行着各自的業務,同時又互爲鏡像備份。此時主機 A 的 /srv/www 目錄同步到主機 B 的 /backups/hosta/www 目錄;主機 B 的 /srv/www 目錄同步到主機 A 的 /backups/hostb/www 目錄等。
-
rsync 命令
rsync 是一個功能很是強大的工具,其命令也有不少功能選項。rsync 的命令格式爲:web
1)本地使用: rsync [OPTION...] SRC... [DEST] 2)經過遠程 Shell 使用: 拉: rsync [OPTION...] [USER@]HOST:SRC... [DEST] 推: rsync [OPTION...] SRC... [USER@]HOST:DEST 3)訪問 rsync 服務器: 拉: rsync [OPTION...] [USER@]HOST::SRC... [DEST] 推: rsync [OPTION...] SRC... [USER@]HOST::DEST 拉: rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST] 推: rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
其中:算法
-
SRC: 是要複製的源位置
-
DEST: 是複製目標位置
-
若本地登陸用戶與遠程主機上的用戶一致,能夠省略 USER@
-
使用遠程 shell 同步時,主機名與資源之間使用單個冒號「:」做爲分隔符
-
使用 rsync 服務器同步時,主機名與資源之間使用兩個冒號「::」做爲分隔符
-
當訪問 rsync 服務器時也可使用 rsync:// URL
-
「拉」複製是指從遠程主機複製文件到本地主機
-
「推」複製是指從本地主機複製文件到遠程主機
-
當進行「拉」複製時,若指定一個 SRC 且省略 DEST,則只列出資源而不進行復制
下面列出經常使用選項:shell
選項 | 說明 |
---|---|
-a, ––archive | 歸檔模式,表示以遞歸方式傳輸文件,並保持全部文件屬性,等價於 -rlptgoD (注意不包括 -H) |
-r, ––recursive | 對子目錄以遞歸模式處理 |
-l, ––links | 保持符號連接文件 |
-H, ––hard-links | 保持硬連接文件 |
-p, ––perms | 保持文件權限 |
-t, ––times | 保持文件時間信息 |
-g, ––group | 保持文件屬組信息 |
-o, ––owner | 保持文件屬主信息 (super-user only) |
-D | 保持設備文件和特殊文件 (super-user only) |
-z, ––compress | 在傳輸文件時進行壓縮處理 |
––exclude=PATTERN | 指定排除一個不須要傳輸的文件匹配模式 |
––exclude-from=FILE | 從 FILE 中讀取排除規則 |
––include=PATTERN | 指定須要傳輸的文件匹配模式 |
––include-from=FILE | 從 FILE 中讀取包含規則 |
––copy-unsafe-links | 拷貝指向SRC路徑目錄樹之外的連接文件 |
––safe-links | 忽略指向SRC路徑目錄樹之外的連接文件(默認) |
––existing | 僅僅更新那些已經存在於接收端的文件,而不備份那些新建立的文件 |
––ignore-existing | 忽略那些已經存在於接收端的文件,僅備份那些新建立的文件 |
-b, ––backup | 當有變化時,對目標目錄中的舊版文件進行備份 |
––backup-dir=DIR | 與 -b 結合使用,將備份的文件存到 DIR 目錄中 |
––link-dest=DIR | 當文件未改變時基於 DIR 建立硬連接文件 |
––delete | 刪除那些接收端還有而發送端已經不存在的文件 |
––delete-before | 接收者在傳輸以前進行刪除操做 (默認) |
––delete-during | 接收者在傳輸過程當中進行刪除操做 |
––delete-after | 接收者在傳輸以後進行刪除操做 |
––delete-excluded | 在接收方同時刪除被排除的文件 |
-e, ––rsh=COMMAND | 指定替代 rsh 的 shell 程序 |
––ignore-errors | 即便出現 I/O 錯誤也進行刪除 |
––partial | 保留那些因故沒有徹底傳輸的文件,以是加快隨後的再次傳輸 |
––progress | 在傳輸時顯示傳輸過程 |
-P | 等價於 ––partial ––progress |
––delay-updates | 將正在更新的文件先保存到一個臨時目錄(默認爲 「.~tmp~」),待傳輸完畢再更新目標文件 |
-v, ––verbose | 詳細輸出模式 |
-q, ––quiet | 精簡輸出模式 |
-h, ––human-readable | 輸出文件大小使用易讀的單位(如,K,M等) |
-n, ––dry-run | 顯示哪些文件將被傳輸 |
––list-only | 僅僅列出文件而不進行復制 |
––rsyncpath=PROGRAM | 指定遠程服務器上的 rsync 命令所在路徑 |
––password-file=FILE | 從 FILE 中讀取口令,以免在終端上輸入口令,一般在 cron 中鏈接 rsync 服務器時使用 |
-4, ––ipv4 | 使用 IPv4 |
-6, ––ipv6 | 使用 IPv6 |
––version | 打印版本信息 |
––help | 顯示幫助信息 |
-
若使用普通用戶身份運行 rsync 命令,同步後的文件的屬主將改變爲這個普通用戶身份。
-
若使用超級用戶身份運行 rsync 命令,同步後的文件的屬主將保持原來的用戶身份。
rsync 的基本使用
在本地磁盤同步數據
# rsync -a --delete /home /backups # rsync -a --delete /home/ /backups/home.0
在指定複製源時,路徑是否有最後的 「/」 有不一樣的含義,例如:ubuntu
-
/home : 表示將整個 /home 目錄複製到目標目錄
-
/home/ : 表示將 /home 目錄中的全部內容複製到目標目錄
使用基於 ssh 的 rsync 遠程同步數據
-
同步靜態主機表文件
# 執行「推」複製同步(centos5 是可解析的遠程主機名) [root@soho ~]# rsync /etc/hosts centos5:/etc/hosts # 執行「拉」複製同步(soho 是可解析的遠程主機名) [root@centos5 ~]# rsync soho:/etc/hosts /etc/hosts
-
同步用戶的環境文件
# 執行「推」複製同步 [osmond@soho ~]$ rsync ~/.bash* centos5: # 執行「拉」複製同步 [osmond@cnetos5 ~]$ rsync soho:~/.bash* .
-
同步站點根目錄
# 執行「推」複製同步 [osmond@soho ~]$ rsync -avz --delete /var/www root@192.168.0.101:/var/www # 執行「拉」複製同步 [osmond@cnetos5 ~]$ rsync -avz --delete root@192.168.0.55:/var/www /var/www
-
使用基於 ssh 的 rsync 同步數據可使用 -e ssh 參數,當前的 CentOS 默認指定使用 ssh 做爲遠程Shell。若您在其餘系統上執行 rsync 命令,爲確保使用 ssh 做爲遠程 Shell,請添加 -e ssh 參數。
-
一般 rsync 命令在後臺以 cron 任務形式執行,爲了不從終端上輸入口令須要設置 ssh。ssh 的設置方法請參考 安全登陸守護進程。
使用 rsync 從遠程 rsync 服務器同步數據
下面以鏡像 CentOS 和 Ubuntu 的軟件庫爲例來講明。
您能夠到以下站點查找離本身最近的提供 rsync 服務的鏡像站點windows
而後執行相似以下命令:centos
rsync -aqzH --delete --delay-updates \ rsync://mirror.centos.net.cn/centos /var/www/mirror/centos rsync -azH --progress --delete --delay-updates \ rsync://ubuntu.org.cn/ubuntu /var/www/mirror/ubuntu/ rsync -azH --progress --delete --delay-updates \ rsync://ubuntu.org.cn/ubuntu-cn /var/www/mirror/ubuntu-cn/
爲了天天不斷更新,能夠安排一個 cron 任務:
# crontab -e # mirror centos at 0:10AM everyday 10 0 * * * rsync -aqzH --delete --delay-updates rsync://mirror.centos.net.cn/centos /var/www/mirror/centos/ # mirror ubuntu at 2:10AM everyday 10 2 * * * rsync -azH --progress --delete --delay-updates rsync://ubuntu.org.cn/ubuntu /var/www/mirror/ubuntu/ # mirror ubuntu-cn at 4:10AM everyday 10 4 * * * rsync -azH --progress --delete --delay-updates rsync://ubuntu.org.cn/ubuntu-cn /var/www/mirror/ubuntu-cn/
若是您安裝了本身的匿名 rsync 服務器請相應地更改 rsync URL。有關如何配置匿名 rsync 服務器的內容請參見下節。
篩選 rsync 的傳輸目標
使用 --exclude/--include 選項
可使用 ––exclude 選項排除源目錄中要傳輸的文件;一樣地,也可使用 ––include 選項指定要傳輸的文件。
例如:下面的 rsync 命令將 192.168.0.101 主機上的 /www 目錄(不包含 /www/logs 和 /www/conf子目錄)複製到本地的 /backup/www/ 。
# rsync -vzrtopg --delete --exclude "logs/" --exclude "conf/" --progress \ backup@192.168.0.101:/www/ /backup/www/
又如:下面的 rsync 命令僅複製目錄結構而忽略掉目錄中的文件。
# rsync -av --include '*/' --exclude '*' \ backup@192.168.0.101:/www/ /backup/www-tree/
選項 ––include 和 ––exclude 都不能使用間隔符。例如:
--exclude "logs/" --exclude "conf/"
不能寫成
--exclude "logs/ conf/"
使用 --exclude-from/--include-from 選項
當 include/exclude 的規則較複雜時,能夠將規則寫入規則文件。使用規則文件能夠靈活地選擇傳輸哪些文件(include)以及忽略哪些文件(exclude)。
-
若文件/目錄在剔除列表中,則忽略傳輸
-
若文件/目錄在包含列表中,則傳輸之
-
若文件/目錄未被說起,也傳輸之
在 rsync 的命令行中使用 ––exclude-from=FILE 或 ––include-from=FILE 讀取規則文件。
規則文件 FILE 的書寫約定:
-
每行書寫一條規則 RULE
-
以 # 或 ; 開始的行爲註釋行
包含(include)和排除(exclude)規則的語法以下:
-
include PATTERN 或簡寫爲 + PATTERN
-
exclude PATTERN 或簡寫爲 - PATTERN
PATTERN 的書寫規則以下:
-
以 / 開頭:匹配被傳輸的跟路徑上的文件或目錄
-
以 / 結尾:匹配目錄而非普通文件、連接文件或設備文件
-
使用通配符
-
*:匹配非空目錄或文件(遇到 / 截止)
-
**:匹配任何路徑(包含 / )
-
?:匹配除了 / 的任意單個字符
-
[:匹配字符集中的任意一個字符,如 [a-z] 或 [[:alpha:]]
-
可使用轉義字符 \ 將上述通配符還原爲字符自己含義
下面給出幾個使用規則的例子:
例1:
# 不傳輸全部後綴爲 .o 的文件 - *.o # 不傳輸傳輸根目錄下名爲 foo 的文件或目錄 - /foo # 不傳輸名爲 foo 的目錄 - foo/ # 不傳輸 /foo 目錄下的名爲 bar 的文件或目錄 - /foo/bar
例2:
# 傳輸全部目錄和C語言源文件並禁止傳輸其餘文件 + */ + *.c - *
例3:
# 僅傳輸 foo 目錄和其下的 bar.c 文件 + foo/ + foo/bar.c - *
將規則寫入規則文件以後,如何在命令行上使用它呢?下面給出一個例子:
首先將下面的規則存入名爲 www-rsync-rules 的文件
# 不傳輸 logs 目錄 - logs/ # 不傳輸後綴爲 .tmp 的文件 - *.tmp # 傳輸 Apache 虛擬主機文檔目錄(/*/ 匹配域名) + /srv/www/ + /srv/www/*/ + /srv/www/*/htdocs/ + /srv/www/*/htdocs/** # 傳輸每一個用戶的 public_html 目錄(/*/ 匹配用戶名) + /home/ + /home/*/ + /home/*/public_html/ + /home/*/public_html/** # 禁止傳輸其餘 - *
而後便可使用相似以下的 rsync 命令:
rsync -av --delete --exclude-from=www-rsync-rules / remotehost:/dest/dir
rsync 應用示例
使用 rsync 鏡像
使用 rsync 對目錄作鏡像實際上就是作無歷史歸檔的徹底備份。下面給出一個鏡像遠程 Web 站點例子。
筆者在 dreamhost 上維護了3個 Dokuwiki 站點。爲了備份這3個站點筆者使用 rsync 進行鏡像。遠程站點的目錄結構以下:
~ |-- sinosmond.com | `-- dokuwiki |-- smartraining.cn | `-- dokuwiki `-- symfony-project.cn `-- dokuwiki
每一個 Dokuwiki 的目錄結構以下:
dokuwiki |-- bin |-- inc |-- conf --- 存放配置文件的目錄 | |-- acl.auth.php --- 訪問控制配置文件 ★ | |-- local.php --- 本地配置文件 ★ | |-- users.auth.php --- 用戶口令文件 ★ | `-- ……………… |-- data --- 存放數據的目錄 | |-- attic --- 存放WIKI版本信息 ★ | |-- cache --- 存放數據緩存 | |-- index --- 存放站內索引 | |-- locks --- 存放編輯頁面時的鎖定文件 | |-- media --- 存放圖片等 ★ | |-- meta --- 存放 meta 以便系統讀取這些信息生成頁面 ★ | `-- pages --- 存放 wiki 頁面 ★ `-- lib |-- plugins --- 存放插件的目錄 ☆ |-- tpl --- 存放模版的目錄 ☆ `-- ………………
爲了減小網絡流量,只同步標有 ★ 的目錄或文件。若在站點運行過程當中新安裝了插件或更換了模板,也應該同步標有 ☆ 的目錄。爲此編寫以下的規則文件 /root/bin/backup/dw-exclude.txt:
- dokuwiki/bin/ - dokuwiki/inc/ - dokuwiki/data/cache/ - dokuwiki/data/locks/ - dokuwiki/data/index/ + dokuwiki/conf/acl.auth.php + dokuwiki/conf/local.php + dokuwiki/conf/users.auth.php - dokuwiki/conf/* + dokuwiki/lib/plugins/ # 不一樣步系統默認安裝的插件 - dokuwiki/lib/plugins/acl/ - dokuwiki/lib/plugins/config/ - dokuwiki/lib/plugins/importoldchangelog/ - dokuwiki/lib/plugins/importoldindex/ - dokuwiki/lib/plugins/info/ - dokuwiki/lib/plugins/plugin/ - dokuwiki/lib/plugins/revert/ - dokuwiki/lib/plugins/usermanager/ - dokuwiki/lib/plugins/action.php - dokuwiki/lib/plugins/admin.php - dokuwiki/lib/plugins/syntax.php + dokuwiki/lib/tpl # 不一樣步系統默認安裝的模板 - dokuwiki/lib/tpl/default/ - dokuwiki/lib/* - dokuwiki/COPYING - dokuwiki/doku.php - dokuwiki/feed.php - dokuwiki/index.php - dokuwiki/install* - dokuwiki/README - dokuwiki/VERSION
下面是同步腳本 /root/bin/backup/rsync-dw.sh
#!/bin/bash ##################################### # mirror dokuwiki website # $1 --- domain (ex: smartraining.cn) # $2 --- full or update ##################################### # declare some variable RmtUser=osmond RmtIP=208.113.163.110 RmtPath=$1/dokuwiki BackupRoot=/backups/$1 Excludes="--exclude-from=/root/bin/backup/dw-exclude.txt" # use rsync for mirror if [ "$2" == "full" ] then [ -d /backups/$1 ] || mkdir -p /backups/$1 excludesfile="/tmp/first-excludes" cat > ${excludesfile} << EOF + dokuwiki/data/cache/_dummy - dokuwiki/data/cache/* + dokuwiki/data/locks/_dummy - dokuwiki/data/locks/* + dokuwiki/data/index/_dummy - dokuwiki/data/index/* EOF /usr/bin/rsync -avzP --exclude-from=${excludesfile} \ $RmtUser@$RmtIP:$RmtPath $BackupRoot else /usr/bin/rsync -avzP --delete $Excludes \ $RmtUser@$RmtIP:$RmtPath $BackupRoot fi
首次備份可使用相似以下的命令(爲了在本地保留一個完整複本):
# /root/bin/backup/rsync-dw.sh smartraining.cn full # /root/bin/backup/rsync-dw.sh sinosmond.com full # /root/bin/backup/rsync-dw.sh symfony-project.cn full
能夠安排 cron 任務以便往後更新:
# crontab -e 05 1 * * * /root/bin/backup/rsync-dw.sh smartraining.cn 25 1 * * * /root/bin/backup/rsync-dw.sh sinosmond.com 45 1 * * * /root/bin/backup/rsync-dw.sh symfony-project.cn
普通型增量備份
使用 rsync 能夠作增量備份。rsync 提供了 -b ––backup-dir 選項,使用這個選項能夠將有變化的文件進行更新同時將其舊版本保存在指定的目錄中,從而實現增量備份。 下面是對 /home 進行增量備份的步驟說明:
# 第0次備份 # 首先複製 /home 目錄的內容到備份目錄 /backups/daily/home.0, # rsync -a /home/ /backups/daily/home.0 # /backups/daily/home.0 老是同步到最新的狀態,能夠每隔一段時間(如一週) # 對其內容進行打包壓縮生成歸檔文件(徹底備份)存在 /backups/archive/。 # 第1次備份(此爲核心操做) # 將 /home 目錄的內容同步到目錄 /backups/daily/home.0, # 並將有變化的文件的舊版本保存到 /backups/daily/home.1, # 若天天執行一次,則目錄 /backups/daily/home.1 保存了有變化文件一天前的狀態。 # rsync -a --delete -b --backup-dir=/backups/daily/home.1 /home/ /backups/daily/home.0 # 第2次備份 # 將備份目錄 /backups/daily/home.1 改名爲 /backups/daily/home.2 # mv /backups/daily/home.1 /backups/daily/home.2 # 執行第1次備份的核心操做 # 第n次備份 # 將早先的備份目錄 /backups/daily/home.n 到 /backups/daily/home.1 # 依次改名爲 /backups/daily/home.(n+1) 到 /backups/daily/home.2 # 執行第1次備份的核心操做
下面給出一個增量備份示例腳本。
#!/bin/bash #======================== # 您能夠安排 cron 任務執行本腳本 # > crontab -e # # daily : 1 1 * * * /path/to/script/rsync-backup.sh #======================== mydate="`date '+%Y%m%d.%H%M'`" # Define rmt location RmtUser=root RmtHost=192.168.0.55 RmtPath=/home/ BackupSource="${RmtUser}@${RmtHost}:${RmtPath}" #BackupSource="/home/" # 若進行本地備份則用本地路徑替換上面的行 # Define location of backup BackupRoot="/backups/$RmtHost/" # BackupRoot="/backups/localhost/" # 若進行本地備份則用本地路徑替換上面的行 LogFile="${BackupRoot}/backup.log" ExcludeList="/root/backup/backup-exclude-list.txt" BackupName='home' BackupNum="7" # 指定保留多少個增量備份(適用於每週生成歸檔文件) #BackupNum="31" # 指定保留多少個增量備份(適用於每個月生成歸檔文件) # 定義函數檢查目錄 $1 是否存在,若不存在建立之 checkDir() { if [ ! -d "${BackupRoot}/$1" ] ; then mkdir -p "${BackupRoot}/$1" fi } # 定義函數實現目錄滾動 # $1 -> 備份路徑 # $2 -> 備份名稱 # $3 -> 增量備份的數量 rotateDir() { for i in `seq $(($3 - 1)) -1 1` do if [ -d "$1/$2.$i" ] ; then /bin/rm -rf "$1/$2.$((i + 1))" mv "$1/$2.$i" "$1/$2.$((i + 1))" fi done } # 調用函數 checkDir ,確保目錄存在 checkDir "archive" checkDir "daily" #======= Backup Begin ================= # S1: Rotate daily. rotateDir "${BackupRoot}/daily" "$BackupName" "$BackupNum" checkDir "daily/${BackupName}.0/" checkDir "daily/${BackupName}.1/" mv ${LogFile} ${BackupRoot}/daily/${BackupName}.1/ cat >> ${LogFile} <<_EOF =========================================== Backup done on: $mydate =========================================== _EOF # S2: Do the backup and save difference in ${BackupName}.1 rsync -av --delete \ -b --backup-dir=${BackupRoot}/daily/${BackupName}.1 \ --exclude-from=${ExcludeList} \ $BackupSource ${BackupRoot}/daily/${BackupName}.0 \ 1>> ${LogFile} 2>&1 # S3: Create an archive backup every week if [ `date +%w` == "0" ] # 每週日作歸檔 # if [ `date +%d` == "01" ] # 每個月1日作歸檔 then tar -cjf ${BackupRoot}/archive/${BackupName}-${mydate}.tar.bz2 \ -C ${BackupRoot}/daily/${BackupName}.0 . fi
您能夠適當修該上述腳本中變量:
RmtPath="$1/" #BackupSource="$1/" BackupName="$1"
而後傳遞腳本參數備份其餘目錄,例如要備份 /www 可使用以下命令:
./rsync-backup.sh /www
快照型增量備份
使用 rsync 能夠作快照(Snapshot)型增量備份。每個快照都至關於一個徹底備份。其核心思想是:對有變化的文件進行復制;對無變化的文件建立硬連接以減小磁盤佔用。
下面是對 /home 進行快照型增量備份的步驟說明:
# 第0次備份 # 首先複製 /home 目錄的內容到備份目錄 /backups/home.0 # rsync -a /home/ /backups/home.0 # 第1次備份(此爲核心操做) # 以硬連接形式複製 /backups/home.0 到 /backups/home.1 # cp -al /backups/home.0 /backups/home.1 # 將 /home 目錄的內容同步到目錄 /backups/home.0 # (rsync 在發現變化的文件時,先刪除之,而後在建立該文件) # rsync -a --delete /home/ /backups/home.0 # 第2次備份 # 將備份目錄 /backups/home.1 改名爲 /backups/home.2 # mv /backups/home.1 /backups/home.2 # 執行第1次備份的核心操做 # 第n次備份 # 將早先的備份目錄 /backups/home.n 到 /backups/home.1 # 依次改名爲 /backups/home.(n+1) 到 /backups/home.2 # 執行第1次備份的核心操做
rsync 2.5.6 版本以後提供了 ––link-dest 選項,以下兩條核心操做命令:
cp -al /backups/home.0 /backups/home.1 rsync -a --delete /home/ /backups/home.0
能夠簡化爲以下的一條命令:
rsync -a --delete --link-dest=/backups/home.1 /home/ /backups/home.0
下面給出一個快照型增量備份示例腳本,該腳原本自http://www.mikerubel.org/computers/rsync_snapshots/contributed/peter_schneider-kamp
#!/bin/bash # ---------------------------------------------------------------------- # mikes handy rotating-filesystem-snapshot utility # ---------------------------------------------------------------------- # RCS info: $Id: make_snapshot.sh,v 1.6 2002/04/06 04:20:00 mrubel Exp $ # ---------------------------------------------------------------------- # this needs to be a lot more general, but the basic idea is it makes # rotating backup-snapshots of /home whenever called # ---------------------------------------------------------------------- # ------------- system commands used by this script -------------------- ID='/usr/bin/id'; ECHO='/bin/echo'; MOUNT='/bin/mount'; RM='/bin/rm'; MV='/bin/mv'; CP='/bin/cp'; TOUCH='/usr/bin/touch'; RSYNC='/usr/bin/rsync'; # ------------- file locations ----------------------------------------- MOUNT_DEVICE=/dev/hdb1; SNAPSHOT_RW=/root/snapshots; EXCLUDES=/etc/snapshot_exclude; # ------------- backup configuration------------------------------------ BACKUP_DIRS="/etc /home" NUM_OF_SNAPSHOTS=3 BACKUP_INTERVAL=hourly # ------------- the script itself -------------------------------------- # make sure we're running as root if (( `$ID -u` != 0 )); then { $ECHO "Sorry, must be root. Exiting..."; exit; } fi echo "Starting snapshot on "`date` # attempt to remount the RW mount point as RW; else abort $MOUNT -o remount,rw $MOUNT_DEVICE $SNAPSHOT_RW ; if (( $? )); then { $ECHO "snapshot: could not remount $SNAPSHOT_RW readwrite"; exit; } fi; # rotating snapshots for BACKUP_DIR in $BACKUP_DIRS do NUM=$NUM_OF_SNAPSHOTS # step 1: delete the oldest snapshot, if it exists: if [ -d ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL}.$NUM ] ; then \ $RM -rf ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL}.$NUM ; \ fi ; NUM=$(($NUM-1)) # step 2: shift the middle snapshots(s) back by one, if they exist while [[ $NUM -ge 1 ]] do if [ -d ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL}.$NUM ] ; then \ $MV ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL}.$NUM ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_IN} fi; NUM=$(($NUM-1)) done # step 3: make a hard-link-only (except for dirs) copy of the latest snapshot, # if that exists if [ -d ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL}.0 ] ; then \ $CP -al ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL}.0 ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL} fi; # step 4: rsync from the system into the latest snapshot (notice that # rsync behaves like cp --remove-destination by default, so the destination # is unlinked first. If it were not so, this would copy over the other # snapshot(s) too! $RSYNC \ -va --delete --delete-excluded \ --exclude-from="$EXCLUDES" \ ${BACKUP_DIR}/ ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL}.0 ; # step 5: update the mtime of ${BACKUP_INTERVAL}.0 to reflect the snapshot time $TOUCH ${SNAPSHOT_RW}${BACKUP_DIR}/${BACKUP_INTERVAL}.0 ; done # now remount the RW snapshot mountpoint as readonly $MOUNT -o remount,ro $MOUNT_DEVICE $SNAPSHOT_RW ; if (( $? )); then { $ECHO "snapshot: could not remount $SNAPSHOT_RW readonly"; exit; } fi;