Chinaunix首页 | 论坛 | 博客
  • 博客访问: 49550
  • 博文数量: 6
  • 博客积分: 207
  • 博客等级: 入伍新兵
  • 技术积分: 68
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-27 14:03
文章分类
文章存档

2012年(6)

我的朋友

分类: LINUX

2012-04-08 07:50:18

    rsync是一个很强大的文件拷贝/备份工具,是cp,scp,cpio,find等命令的综合体.大部分需要这些工具用管道组合才能实现的功能,可以通过rsync强大的一行命令解决.rsync的学习之路分为三个阶段:
1.基本的命令行与常用选项
2.远程服务配置
3.文件过滤功能

阶段1 
    根据man rsync的手册上的介绍,rsync一共有最多八种功能,但其实也就是个噱头,总的来说是两类功能
1.本地拷贝,命令行:    rsync [OPTION]... src [src]... dest
比如,把/etc目录下的*.conf文件拷贝到dir目录下:
rsync -avzP /etc/*.conf ./
这条命令基本上相当于cp,但还有一些其它的cp做不到的玩法
2.远程拷贝.rsync支持"本地->远程","远程->本地"双方拷贝,不支持"远程->远程"拷贝.rsync的网络功能通过两种方式:ssh服务和rsync --daemon服务.命令行有三种形式(只介绍本地->远程模式):
rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST 这种形式和scp很像,大家应该很熟悉,比如
rsync avz *.c foo:/home/user1/src/
把当前目录下的c语言拷贝到foo主机下的src目录下.在输入命令后,会要求你输入密码.当然不带user@时是使用当前用户.这个逻辑与scp和rcp相同.这种模式就是通过ssh服务实现的
       rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST 这种形式跟第一种相比就是多了个:,但意义不同.需要HOST端的rsync服务支持.比如:
rsync avz *.c foo::src/
把当前目录下的c语言拷贝到foo主机下的src标签定义的目录下.主机与用户名格式不变,但此处的src不同于上.此种的src是服务端rsyncd.conf里定义的标签名.该标签定义了目录名,各种权限等,比如一个典型的:
[src] path = /home/user1/src comment = ftp export area 定义了src这个tag的路径和介绍.其它还有user,密码文件,权限等属性可以定义
       rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST 这种形式同上,也需要HOST商的rsync的服务支持.这是rsync特有的一种形式,其特点在于可以查看远程的文件有什么而不一定要拷贝.查看的命令即是只要一个参数, 比如:
[work@10.81.52.135]~>$ rsync rsync://10.81.47.94
data            It's my fucking data!
etc             It's etc
[work@10.81.52.135]~>$ rsync rsync://10.81.47.94/data
Password: 
@ERROR: auth failed on module data
rsync: connection unexpectedly closed (0 bytes received so far) [receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(359)
[work@10.81.52.135]~>$ rsync rsync://10.81.47.94/data --password-file=pss 
drwxrwxrwx        4096 2012/04/08 07:26:34 .
-rw-------        4522 2012/04/01 20:44:45 .bash_history
-rw-r--r--         304 2010/08/19 19:54:33 .bash_logout
-rw-r--r--        1620 2012/04/01 12:04:49 .bash_profile
-rw-r--r--         124 2010/08/19 19:54:33 .bashrc
drwx------        4096 2010/09/15 15:24:14 .bssh
-rw-r--r--         383 2010/08/19 19:54:33 .emacs
drwx------        4096 2010/09/15 15:24:14 .ssh
-rw-------        7962 2012/04/01 15:34:05 .viminfo
-rw-r--r--         658 2010/08/19 19:54:33 .zshrc
-rw-rw-r--    91678576 2012/03/29 17:18:54 acd_ims.tar.gz
drwxrwxrwx        4096 2012/04/01 14:06:32 creampie
-rw-rw-r--           8 2012/04/08 07:26:34 ff
drwxrwxr-x        4096 2010/09/15 15:23:28 opbin
drwxrwxr-x        4096 2010/09/15 15:23:10 opdir
drwxrwxrwx        4096 2012/04/08 05:43:34 ss
drwxrwxrwx        4096 2012/04/01 15:25:02 wx

看上去是不是很像ftp的效果.只是rsync的查看是一次性的,不支持命令行二次操作.


现在,我们来看看rsync的选项.rsync继承了unix一贯的man死人的风格,选项多的令人发指.不信可以直接输入rsync回车.但一般常用的就以下几个:
   -H 保留源文件的硬链接文件
    -r 递归模式,包含目录及子目录的所有信息
    -z 在传输文件的同时进行压缩
    -v 显示同步过程的信息
    -t 保留文件的时间标记
    -o 保留文件的属主标记
    -p 保留了文件的权限标记
    -D 保留了设备文件和一些特殊的文件
    -S 对零散文件的处理
    -g 保留了文件的属组信息
但这些都太烦了,rsync考虑到这一点,提供了-a选项.它相当于-rlptgoD,几乎是一锅端的概念.考虑到大文件和网络问题再加上-z压缩.考虑到码农的强迫症,有像我一样喜欢欣赏cpu努力干活的时候刷出来一屏一屏的数据的,加上-v.如果还嫌不够细致,就加上--progress.如果嫌麻烦,就改成-P,外送一个--partial.所以对我来说,传文件的标配是 -avzP.
   另外,rsync有一些其它的选项需要了解:
--deamon 后台模式,这就是起rsync服务的命令.牛x吧,这一个程序又可以起服务端又可以当客户端用.我还是第一次见到.deamon模式下有一些它所特有的参数
--include/exclclude/filter 过滤规则,rsync特有的文件提取和过滤,后面会讲到
-e --rsh=COMMAND           specify the remote shell
  -b, --backup                make backups (see --suffix & --backup-dir)
-n, --dry-run show what would have been transferred.这个相当于是在你定义好过滤规则后,没有把握是不是完全正确,使用这个命令rsync会把将要传送的文件名列出来但不执行拷贝动作,相当于直接把过滤规则解释出来给你看.当然你不定义过滤规则就是你要求的所有文件了

  基本上,了解上面这些选项,客户端的功能大多都够用了.

阶段2.rsync服务端配置.
上面已经说过了,rsync是一个C/S杂交体,它就一个程序即可以当客户端也可以当服务端用.--daemon一秒钟变身服务端. /etc/services文件里记录了rsync默认使用873号端口.当然像别的服务一样,rsync同样是需要配置文件的.rsync默认是找/etc/rsyncd.conf.有两点比较奇怪,一是居然用的rsyncd这个名字,二是默认/etc目录下没有这个文件.当然我们新建一个就好了.具体的格式大家可以man一下rysncd.conf,里面有详细的介绍.其实就跟samba这种比较类似,下面是一个简单的rsyncd.conf:
#指定访问组
gid = nobody
#禁止chroot(不可连接后切换用户) 
use chroot = no  
#允许访问目录列表
list = yes   
#最大的连接数为10
max connections = 10       
#存放进程标识文件的路径
pid file = /var/run/rsyncd.pid 
#存放日志文件的路径
log file = /var/log/rsyncd.log 
#允许访问rsync 服务的地址范围
hosts allow = 10.81.0.0/16
 
#此为开放的tag:
[data]
    path = /home/work
    #注释信息,有印象吗,这个信息出现在 rsync rsync://xxxxxx的浏览输出中
    comment = It's my fucking data!   
    #标识为可读
    read only = yes   
    #授权的用户名
    auth users = work    
    #授权用户的密码文件位置    
    secrets file = /etc/rsyncd.pass  
[etc]
    path = /etc
    #注释信息
    comment = It's etc
 
开头定义全局参数,在每个tag里可以自己定义自己的玩法.全局的参数大多比较好理解,不好理解的一般也用不上.在man rsyncd.conf里有详细的介绍.tag里必须要有的是path,指定了你能aceess的目录.注意user的权限问题.然后一个重要的就是secrets file.通过它可以实现scp让人一直很难避免的手动输入密码问题.
对于这个配置文件,我要强调一下.注释不要写在一行的后面,一定要用#顶行写.因为我做过测试,在1.62这个版本上,注释和配置写在一行会导致rsync服务出错.可恶的是它居然不报错,就是连不上,而且出错信息尽是auth failed这种,让你以为自己密码填错了.连日志都没有,查起来非常麻烦.而且最好用英文写注释.码农的世界不欢迎acsill码外的符号.
rsync支持--config-file选项,指定配置文件(值得注意的一点是,这个老版本的ms找不到配置文件,rsync会无声无息的退出,一句话都不打出来,给人一种它在后台服务的假象.新的版本解决了这个问题).其它还有杂七杂八的选项关于配置这块的.
对于rsync这种服务,可以用命令行起独立模式,但一般都交给xinetd托管.只需要修改/etc/xinetd.d/rsync里的disable,改成no,然后重启xinetd服务,即:
sed -i '/disable/s/=.*$/= no/' /etc/xineted.d/rsync && /etc/init.d/xinetd restart 
使用chkconfig --list 和netstat -tnpl|grep xinetd查看,一个on一个监听873端口,说明rsync服务已准备好.
[root@10.81.47.94~]# chkconfig --list rsync
rsync           on
[root@10.81.47.94~]# netstat -tnpl|grep xinetd
tcp        0      0 0.0.0.0:873                 0.0.0.0:*                   LISTEN      2473/xinetd         

此时,在客户端可以用后两种网络模式连了.如

[work@10.81.52.135]~/haha>$ rsync -avzP 10.81.47.94::data/ss ./
Password: 
receiving file list ... 
15 files to consider
ss/
ss/aa -> /home/work/
ss/bigfile
   838860800 100%   68.24MB/s    0:00:11  (1, 20.0% of 15)
ss/ff
          21 100%    0.03kB/s    0:00:00  (2, 26.7% of 15)
ss/file0
     1048576 100%    1.60MB/s    0:00:00  (3, 33.3% of 15)
ss/file1
     1048576 100%    1.59MB/s    0:00:00  (4, 40.0% of 15)
ss/file2
     1048576 100%    1.49MB/s    0:00:00  (5, 46.7% of 15)
ss/file3
     1048576 100%    1.48MB/s    0:00:00  (6, 53.3% of 15)
ss/file4
     1048576 100%    1.46MB/s    0:00:00  (7, 60.0% of 15)
ss/file5
     1048576 100%    1.45MB/s    0:00:00  (8, 66.7% of 15)
ss/file6
     1048576 100%    1.39MB/s    0:00:00  (9, 73.3% of 15)
ss/file7
     1048576 100%    1.38MB/s    0:00:00  (10, 80.0% of 15)
ss/file8
     1048576 100%    1.36MB/s    0:00:00  (11, 86.7% of 15)
ss/file9
     1048576 100%    1.35MB/s    0:00:00  (12, 93.3% of 15)
ss/gcc.inf
     1245769 100%    1.50MB/s    0:00:00  (13, 100.0% of 15)

sent 367 bytes  received 1141032 bytes  69175.70 bytes/sec
total size is 850592361  speedup is 745.22
当然也可以使用第三种模式查看:

[work@10.81.47.94]~/ss>$ rsync rsync://10.81.47.94/data/ss/
Password: 
drwxrwxr-x        4096 2012/04/08 05:43:34 .
lrwxrwxr-x          11 2012/04/08 04:39:59 aa
-rw-rw-r--   838860800 2012/04/08 05:43:34 bigfile
-rw-rw-r--          21 2012/04/08 04:35:37 ff
-rw-rw-r--     1048576 2012/04/08 04:37:12 file0
-rw-rw-r--     1048576 2012/04/08 04:37:12 file1
-rw-rw-r--     1048576 2012/04/08 04:37:12 file2
-rw-rw-r--     1048576 2012/04/08 04:37:12 file3
-rw-rw-r--     1048576 2012/04/08 04:37:12 file4
-rw-rw-r--     1048576 2012/04/08 04:37:12 file5
-rw-rw-r--     1048576 2012/04/08 04:37:12 file6
-rw-rw-r--     1048576 2012/04/08 04:37:12 file7
-rw-rw-r--     1048576 2012/04/08 04:37:12 file8
-rw-rw-r--     1048576 2012/04/08 04:37:12 file9
-rw-rw-r--     1245769 2012/04/08 05:41:48 gcc.inf

到现在,rsync在我们看来只是一个cp和scp的集合体而已.但后面讲到的rsync的功能,应该是很多同志们很想要的.
配置secrets file可以实现无密码拷贝.这比用expect包装scp或者ssh相互配置信任或者用python的pxssh之流要爽多了.当然两台ssh相互信任的主机通过第一种网络模式也是可以无密码拷贝的.
secrets file就是上面提到的conf里配置的密码文件,一般放在etc目录下,纯文本.这个文件有两点要注意:一是权限设成600,二是格式为"user:password",仅此一行.最好不要多空格少空格的,以免夜长梦多.user是与该secrets file同tag下定义的user名称相同,password自己随便写.比如work:abcd.同时,在客户端上配置一个同样的文件,文件名随意(例如pss),位置随意,同样两点要求:一是权限设成600,二是只写入password,不要user:,即服务端定义的abcd.处理完这些后,在客户端使用 --password-file=pss,就可以无密码拷贝了.我觉得这个比较好的一点是密码自己定义,变算暴露了也不会影响work的登陆密码.rsync有自己的一套权限管理.

阶段3 使用过滤功能.rsync有着自己定义的一套过滤语法,很强大但是语法很怪异,秉承了unix家庭一贯的传统.而且由于我这里的rsync版本很老,只有1.6.2,新的现在已经3.0.9了.我只好做了个虚拟机装了个新的os.这样就没办法做网络测试了,但本地的逻辑是一样.来看看:
[QThread@Heineken ss]$ tree ../aa
../aa
|-- 1.a
|-- 1.b
|-- 1.c
`-- dir
    |-- 2.a
    |-- 2.c
    `-- dir2
        |-- 3.a
        |-- 3.b
        `-- 3.c

2 directories, 8 files
把目录aa下的所有.a文件拷贝到当前目录下(所有都是保留目录的):
[QThread@Heineken ss]$ rm -rf * && rsync -avz --filter='+ */' --filter='+ *.a' --filter='- *' ../aa/ ./ && tree .
sending incremental file list
./
1.a
dir/
dir/2.a
dir/dir2/
dir/dir2/3.a

sent 3186 bytes  received 80 bytes  6532.00 bytes/sec
total size is 14660  speedup is 4.49
.
|-- 1.a
`-- dir
    |-- 2.a
    `-- dir2
        `-- 3.a
还有另一种方法:
[QThread@Heineken ss]$ rm -rf * && rsync -avz --filter='+ */' --filter='-! *.a' ../aa/ ./ && tree .
sending incremental file list
./
1.a
dir/
dir/2.a
dir/dir2/
dir/dir2/3.a

sent 3186 bytes  received 80 bytes  6532.00 bytes/sec
total size is 14660  speedup is 4.49
.
|-- 1.a
`-- dir
    |-- 2.a
    `-- dir2
        `-- 3.a

2 directories, 3 files
稍微解释一下,其实我也只是一知半解.filter是定义过滤条件,一个过滤条件分两个部分:rule和patten,两个通过空格或者下划线相连.我这里都用的是空格.3.0.9版本一共支持以下几种rule:
exclude, - specifies an exclude pattern. 
include, + specifies an include pattern. 
merge, . specifies a merge-file to read for more rules. 
dir-merge, : specifies a per-directory merge-file. 
hide, H specifies a pattern for hiding files from the transfer. 
show, S files that match the pattern are not hidden. 
protect, P specifies a pattern for protecting files from deletion. 
risk, R files that match the pattern are not protected. 
clear, ! clears the current include/exclude list (takes no arg) 
实话说,本人英文水平实在有限,大部分没看懂.只会用前两个.前两个的意思就是一个是包含,一个是剔除.如果没有匹配的,就默认包含,这就是为什么每个后面都要有个exclude的filter的意思.因为第一个filter已经定义是包含了所有目录,所以如果不剔除的话就相当于啥都拷贝了.大家可以试一试.
对于patten,这是个非常奇怪的逻辑,本人英文水平实在有限,绝大部分没看懂.有各种匹配,各种符号,*/,**/,**都是不同的意思.下面给出man rsync里的几个例子,结合例子看应该还是能懂一点的:
  • "- *.o" would exclude all names matching *.o
  • "- /foo" would exclude a file (or directory) named foo in the transfer-root directory
  • "- foo/" would exclude any directory named foo
  • "- /foo/*/bar" would exclude any file named bar which is at two levels below a directory named foo in the transfer-root directory
  • "- /foo/**/bar" would exclude any file named bar two or more levels below a directory named foo in the transfer-root directory
  • The combination of "+ */", "+ *.c", and "- *" would include all directories and C source files but nothing else (see also the --prune-empty-dirsoption)
  • The combination of "+ foo/", "+ foo/bar.c", and "- *" would include only the foo directory and foo/bar.c (the foo directory must be explicitly included or it would be excluded by the "*")
对于第一个例子,我们要提取所有*.a的文件,第一个条件一般都需要,就是包含所有当前目录和其子目录.第二个条件就是包含我们要过滤的.a文件,第三个条件是剔除所有其它的文件.这个时候大家可能会问到,为什么这么麻烦,有了第二个为什么还要第一个.好,我们来看看:
[QThread@Heineken ss]$ rm -rf * && rsync -avz --filter='+ *.a' --filter='- *' ../aa/ ./ && tree .
sending incremental file list
./
1.a

sent 2918 bytes  received 34 bytes  5904.00 bytes/sec
total size is 14540  speedup is 4.93
.
`-- 1.a

0 directories, 1 file
看到没有,如果没有第一个条件,子目录下的.a就全部被忽略了.这还不如不用filter直接../aa/*.a来的实在.
对于第二个例子,同样是提取所有*.a,我们在最后一个-filter里做文章,加了一个!,就是否的意思.意思是包含所有文件,剔掉所有不是*.a的文件.一样达到了效果
那么对于第三个例子就简单了,提取所有的*.a和*.b文件.当然我们举一反三,如果有需求剔掉所有.b文件呢,应该这么写:
 rsync -avz --filter='+ */' --filter='- *.c' ../aa/ ./
如果有需求,不要文件,只取出所有的目录结构呢,可以这样:
[QThread@Heineken ss]$ rm -rf * && rsync -avz --filter='+ */' --filter='- *' ../aa/ ./ && tree .sending incremental file list
./
dir/
dir/dir2/

sent 93 bytes  received 23 bytes  232.00 bytes/sec
total size is 0  speedup is 0.00
.
`-- dir
    `-- dir2

2 directories, 0 files
如果有需求,不要目录,取出来的所有*.a都放在当前目录下呢,我诚恳的告诉大家,我研究了半天也不知道怎么弄.但我直觉告诉我一定可以,只是本人资质有限罢了.
反正就是这个意思了,能不能领悟就看同志们的造化了.当然这些功能通过find+tar的命令在本地同样可以做到,例如:
cd ../aa && find . -name '*.a'|xargs tar cvf -|(cd ../ss && tar xvf -)
  但是,find+tar可以从远程过滤文件拷贝回本地吗?scp可以做到.但scp只能使用原始的通配符,scp我印象中好像无法有很强的过滤文件的功能.对于rsync来说,这一切都不是它一行命令解决的问题.rsync的强大功能,我今天讲到的只能说是冰山的一角,今天只能说是简单的给大家介绍了一下rsync,如果有什么没讲清楚的地方,其实我也不一定清楚...
最后说一句,排版不好,敬请见谅


 
阅读(5416) | 评论(1) | 转发(0) |
1

上一篇:没有了

下一篇:linux 查看线程id与信息

给主人留下些什么吧!~~

少林功夫好2017-01-11 11:13:05

很好的分享。虽然有些小出入,无伤大雅。感谢感谢