rsync 精確同步檔案用法
阿新 • • 發佈:2019-02-11
使用 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
#!/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;