Rsync (简体中文)
rsync 是一个开源工具,可以进行快速的增量文件传输。
安装
必须在源计算机和目标计算机上都安装 rsync 。
前端
- Grsync — GTK 前端。
- gutback — 使用 Shell 编写的 rsync 包装。
- JotaSync — 用于 rsync 的 Java Swing GUI,带有内置计划功能。
- luckyBackup — 用 C++ 编写的 Qt 前端。
其他使用 rsync 的工具有 rdiff-backup 和 osyncAUR。
作为 cp 的替代
rsync 可以作为 cp
或 mv
命令的高级替代品,特别是对于较大文件的复制:
$ rsync -P source destination
其中 -P
与 --partial --progress
选项的作用是相同的,该选项使得文件可以分块传输并显示传输过程中的进度。
您可能需要使用 -r
/--recursive
选项递归到目录中传输。
可以像 cp 命令一样本地复制文件,但 rsync 令人激动的用途在于远程复制文件,例如在两个不同的主机之间。远程位置可以用主机加冒号进行指定:
$ rsync source host:destination
或者
$ rsync host:source destination
网络文件传输默认使用SSH协议,host
可以是真实的主机名或来自于 .ssh/config
的预先定义的配置文件/别名。
无论是本地或远程文件传输, rsync 首先会创建一个文件列表,其中含有接下来会被用于确定各个文件是否需要构建的信息(默认为文件大小和上次修改时间戳)。对于每个需要构建的文件,都会找出其所有块(长度S字节,不重叠,偏移量可由S整除)的一个弱校验和和一个强校验和。使用这一信息,一个大文件就可以由 rsync 构建,而无需传输整个文件。更详细的实际解释和详细的数学解释见 rsync 如何工作 及 rsync 算法。
要快速使用合理默认值,可以使用一些别名:
function cpr() { rsync --archive -hh --partial --info=stats1,progress2 --modify-window=1 "$@" } function mvr() { rsync --archive -hh --partial --info=stats1,progress2 --modify-window=1 --remove-source-files "$@" }
--checksum
选项的行为不是相等价的。--checksum
选项影响的是在传输任何文件之前使用的决定是否跳过文件的启发式方法。在基于块的文件构建中一定会使用校验和,这是 rsync 传输文件的方法,与 --checksum
无关。注意尾随下划
Arch 默认使用 GNU cp (GNU coreutils 的一部分)。 然而,rsync 遵循 BSD cp 的约定, 源目录后面带有一个斜杠“/”有着特定的处理。比如:
$ rsync -r source destination
创建一个有着 "source"内容的 "destination/source"目录,命令:
$ rsync -r source/ destination
把"source/"目录下的所有文件全部复制到"destination"目录下,而没有中间的子目录 - 就像你调用了:
$ rsync -r source/. destination
这与 GNU cp 的行为是不同的,在GNU cp中"source" 与 "source/" 意义相同 ("source/."则不然)。并且,一些shell在Tab补全目录名的时候自动追加尾部下划线。由于这些因素,新手或偶尔使用 rsync 的用户可能倾向于忘记rsync的不同行为,在命令行上留下了结尾的下划线,从而无意间造成混乱,甚至覆盖重要文件。
谨慎起见,可以使用包装脚本在调用rsync之前自动删除尾部斜杠:
#!/bin/zsh new_args=(); for i in "$@"; do case $i in /) i=/;; */) i=${i%/};; esac new_args+=$i; done exec rsync "${(@)new_args}"
该脚本可以放在 path 中的某个位置,并在 shell 的 init 文件中指定别名为 rsync。
作为备份工具
rsync协议可以很容易地用于备份,只传输自上次备份以来已更改的文件。本节将介绍一个非常简单的基于rsync的计划备份脚本,通常用于复制到可移动介质。对于更详尽的例子, 保留一些系统文件所需的附加选项, 参见 Full system backup with rsync.
自动备份
以下面的脚本为例,该脚本放置于 /etc/cron.daily
目录下,如果 cron daemon 被正确安装和配置,它将每天运行。配置和使用 cron 是本文的范围之外。
首先,创建一个包含相应命令选项的脚本:
/etc/cron.daily/backup
#!/bin/bash rsync -a --delete /folder/to/backup /location/of/backup &> /dev/null
-a
- 表示文件应被存档,这意味着他们的大部分特性被保留 (不包括ACLs, 硬链接或扩展属性,如capabilities)
--delete
- 指同步源文件的删除操作。
在这里,/folder/to/backup
应该改成需要被备份的路径 (比如 /home
),/location/to/backup
是备份应存放的位置 (比如 /media/disk
).
最后,脚本必须是可执行的:
# chmod +x /etc/cron.daily/backup
自动用 SSH 备份
如果是通过 SSH 备份到远程主机,改为使用此脚本:
/etc/cron.daily/backup
#!/bin/bash rsync -a --delete -e ssh /folder/to/backup remoteuser@remotehost:/location/of/backup &> /dev/null
-e ssh
- 告诉rsync的使用SSH
remoteuser
:远程主机remotehost
上的用户名-a
- 组中的所有这些选项
-rlptgoD
(recursive, links, perms, times, group, owner, devices)
自动使用NetworkManager备份
该脚本在你接入网络后开始备份。
首先,创建一个包含相应命令选项的脚本:
/etc/NetworkManager/dispatcher.d/backup
#!/bin/bash if [ x"$2" = "xup" ] ; then rsync --force --ignore-errors -a --delete --bwlimit=2000 --files-from=files.rsync /folder/to/backup /location/to/backup fi
-a
- 组中的所有选项
-rlptgoD
recursive, links, perms, times, group, owner, devices --files-from
- 从文件中读取到备份路径/folder/to/backup的相对路径
--bwlimit
- 限I / O带宽;每秒千字节
Also, the script must have write permission for owner (root, of course) only (see NetworkManager dispatcher for details).
使用systemd和inotify自动备份
- Due to the limitations of inotify and systemd (see this question and answer), recursive filesystem monitoring is not possible. Although you can watch a directory and its contents, it will not recurse into subdirectories and watch the contents of them; you must explicitly specify every directory to watch, even if that directory is a child of an already watched directory.
- This setup is based on a systemd/User instance.
Instead of running time interval backups with time based schedules, such as those implemented in cron, it is possible to run a backup every time one of the files you are backing up changes. systemd.path
units use inotify
to monitor the filesystem, and can be used in conjunction with systemd.service
files to start any process (in this case your rsync backup) based on a filesystem event.
First, create the systemd.path
file that will monitor the files you are backing up:
~/.config/systemd/user/backup.path
[Unit] Description=Checks if paths that are currently being backed up have changed [Path] PathChanged=%h/documents PathChanged=%h/music [Install] WantedBy=default.target
Then create a systemd.service
file that will be activated when it detects a change. By default a service file of the same name as the path unit (in this case backup.path
) will be activated, except with the .service
extension instead of .path
(in this case backup.service
).
Type=oneshot
. This allows you to specify multiple ExecStart=
parameters, one for each rsync command, that will be executed. Alternatively, you can simply write a script to perform all of your backups, just like cron scripts.~/.config/systemd/user/backup.service
[Unit] Description=Backs up files [Service] ExecStart=/usr/bin/rsync %h/./documents %h/./music -CERrltm --delete ubuntu:
Now all you have to do is start/enable backup.path
like a normal systemd service and it will start monitoring file changes and automatically starting backup.service
.
一个星期差异备份
这个 rsync 选项很有用,可以每日创建全量或增量备份。
首先,创建一个包含相应命令选项的脚本:
/etc/cron.daily/backup
#!/bin/bash DAY=$(date +%A) if [ -e /location/to/backup/incr/$DAY ] ; then rm -fr /location/to/backup/incr/$DAY fi rsync -a --delete --inplace --backup --backup-dir=/location/to/backup/incr/$DAY /folder/to/backup/ /location/to/backup/full/ &> /dev/null
--inplace
- implies
--partial
update destination files in-place
快照备份
The same idea can be used to maintain a tree of snapshots of your files. In other words, a directory with date-ordered copies of the files. The copies are made using hardlinks, which means that only files that did change will occupy space. Generally speaking, this is the idea behind Apple's TimeMachine.
This basic script is easy to implement and creates quick incremental snapshots using the --link-dest
option to hardlink unchanged files:
/usr/local/bin/snapbackup.sh
#!/bin/bash # Basic snapshot-style rsync backup script # Config OPT="-aPh" LINK="--link-dest=/snapshots/username/last/" SRC="/home/username/files/" SNAP="/snapshots/username/" LAST="/snapshots/username/last" date=`date "+%Y-%b-%d:_%T"` # Run rsync to create snapshot rsync $OPT $LINK $SRC ${SNAP}$date # Remove symlink to previous snapshot rm -f $LAST # Create new symlink to latest snapshot for the next backup to hardlink ln -s ${SNAP}$date $LAST
There must be a symlink to a full backup already in existence as a target for --link-dest
. If the most recent snapshot is deleted, the symlink will need to be recreated to point to the most recent snapshot. If --link-dest
does not find a working symlink, rsync will proceed to copy all source files instead of only the changes.
A more sophisticated version checks to see if a certain number of changes have been made before making the backup and utilizes cp -al
to hardlink unchanged files:
/usr/local/bin/rsnapshot.sh
#!/bin/bash ## my own rsync-based snapshot-style backup procedure ## (cc) marcio rps AT gmail.com # config vars SRC="/home/username/files/" #dont forget trailing slash! SNAP="/snapshots/username" OPTS="-rltgoi --delay-updates --delete --chmod=a-w" MINCHANGES=20 # run this process with real low priority ionice -c 3 -p $$ renice +12 -p $$ # sync rsync $OPTS $SRC $SNAP/latest >> $SNAP/rsync.log # check if enough has changed and if so # make a hardlinked copy named as the date COUNT=$( wc -l $SNAP/rsync.log|cut -d" " -f1 ) if [ $COUNT -gt $MINCHANGES ] ; then DATETAG=$(date +%Y-%m-%d) if [ ! -e $SNAP/$DATETAG ] ; then cp -al $SNAP/latest $SNAP/$DATETAG chmod u+w $SNAP/$DATETAG mv $SNAP/rsync.log $SNAP/$DATETAG chmod u-w $SNAP/$DATETAG fi fi
To make things really, really simple this script can be run from a systemd/Timers unit.