1. 程式人生 > >rsync 精確同步檔案用法

rsync 精確同步檔案用法

使用 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;