使用rsync代替scp上传文件到服务器或从服务器下载文件(支持跨越跳板机)

使用rsync代替scp上传文件到服务器或从服务器下载文件(支持跨越跳板机)

之前写过一篇使用scp实现类似功能的文章:
使用scp上传文件到服务器或从服务器下载文件(支持跨越跳板机)

还写过两篇rsync相关的文章:
使用sersync +rsync进行实时文件同步
CentOS7部署lsyncd+rsync实现服务器文件实时同步

什么是rsync?

运行man rsync命令,可以看到它的解释是“rsync – faster, flexible replacement for rcp”,意思是“更加快速,灵活的rcp的代替”,意思是它比rcp更加快速,灵活,用于代替rcp。至于什么是rcp呢?rcp是remote copy,用于远程拷贝的命令,我也没有用过这个命令,看上去它应该是已经被rsync替代了。

据我实际使用所知,rsync是一个可以让你上传文件到服务器或从服务器下载文件的工具,它的优点是可以断点续传、增量同步(具有相同功能的scp就没有这两个功能),而且还安全(既可以通过ssh通道,也可以通过它自身的协议)。

实例演示

这里只说不需要搭建rsyncd服务器的方式,不搭建服务器的方式其实是通过ssh通道来传输的,所以下边的命令基本上都会弹出要你输入ssh的密码(除非你做了免密登录)。

需要搭建rsyncd服务器的同步方式可以看使用sersync +rsync进行实时文件同步这篇文章。

从本地拷贝到本地

本地拷贝到本地有一个现实场景,就是你的网站有test版的和正式版的,每次更新前用git从仓库检出到test版目录中,然后在test版中测试没问题后,再把代码同步到正式版的目录中,这时就可以用rsync,因为rysnc可以同步更新的文件(目标目录中该文件修改时间比源目录旧,就会被更新,但如果比源目录新,就不会被强制覆盖),而单纯的cp命令做不到这个。

以下命令会把./rsync1/目录中的全部文件(包括里面的目录)同步到./rsync2/目录中

rsync -rP --delete ./rsync1/ ./rsync2/

--delete表示会把./rsync2/中存在而./rsync1/中不存在的文件删掉(以达到两个目录完全一样的目的)。
-r表示recursive,递归操作,使用--delete选项时必须使用-r,否则报错,原因是使用--delete后,源和目的必须都是目录(如果其中一个不是目录,虽然不报错,但是--delete不会起作用),而如果两个都是目录,则必须用-r,Linux中绝大部分命令在操作目录时,都使用-r-R(表示递归执行操作)。
-P表示同时启用--progress+--partial选项,--progress表示显示传输进度,而--partial表示不删除中断传输的文件(默认情况下如果有文件传输过程中断了,也就是只传了一部分,rsync会把已经传输的部分删除,相当于白传了,而加了--partial选项后就不会删除,其实该选项就是开启断点续传)。

本地拷贝到远程(上传文件到服务器)

把当前目录下的local_file.txt文件传到ip为12.32.56.78的服务器中

rsync -azP ./local_file.txt [email protected]:~

其中xiebruce是用来登录远程服务器的用户名,~表示把文件传到xiebruce这个用户的家目录中,这是典型的ssh登录格式,因为它其它是通过ssh通道来传输的,所以如果你没有设置免密登录,它就会弹出让你输入密码的提示,你输入你的ssh登录密码即可。

  • -a表示archive,打包/归档
  • -z表示compress,即压缩,再次说明,打包是打包,压缩是压缩,打包未必会压缩,但压缩一定会打包。
  • -P表示显示传输进程--progress和断点续传--partial,具体见从本地拷贝到本地
  • -u不制覆盖远程服务器的文件(比如服务器上有一个aaa文件比你本地aaa文件还新,比如线上的aaa文件被你修改过,则用-u选项后就不会用本地的覆盖线上的)。

从本地拷贝到本地中说过的一样,如果你需要你本地的某个目录与远程服务器的某个目录数据完全同步,你需要添加--delete选项以及-r选项。

举例:把当前目录下的test目录与远程服务器xiebruce用户目录下的test目录数据完全同步

rsync -azrP ./test/ [email protected]:~/test/

同时传多个文件到服务器(空格隔开就行)

rsync -azP ./ccc ./ddd [email protected]:~/test/

如果服务器ssh端口不是默认端口,则要通过-e选项来指定ssh端口ssh -p 2222

rsync -azP -e 'ssh -p 2222' ./ccc ./ddd [email protected]:~/test/

从远程拷贝到本地(从远程服务器下载文件)

就是把从本地拷贝到远程的源和目标两个参数反过来写就行。

从远程服务器下载/home/zhangsan/file1.txt文件到本地当前目录./

rsync -azP [email protected]:/home/zhangsan/file1.txt ./

操作目录加-r,完全同步两个目录加--delete这我就不写示例了,跟前面的一样。

远程拷贝到远程(两个远程服务器之间拷贝)

没有直接的方法,貌似可以通过ssh -A,但我试了不行,这里有提到:How to rsync files between two remotes?

所以这也是scp的优点之一,scp可以做到远程与远程之间拷贝:远程拷贝到远程(两个远程服务器之间拷贝)

rsync跨越跳板机

通过跳板机把本地的test_from_rsync1文件上传到远程服务器的~/rsynctest/

rsync -azP -e 'ssh -J [email protected]:22' ./rsync1/test_from_rsync1 [email protected]:~/rsynctest/

从远程服务器下载

rsync -azP -e 'ssh -J [email protected]:22' [email protected]:~/rsynctest/test_from_rsync1 ./rsync1/

与scp类似,都是通过ssh的代理来跨越的,与前面的命令不同的地方就是添加了以下这句,其中-J就是--proxyJump

-e 'ssh -J [email protected]:22'

同理,这个选项也可以在ssh配置文件~/.ssh/config中配置而不是直接写在命令里(太长太麻烦了)

# 定义跳板机
Host jump
    HostName 11.22.33.44
    User xiebruce
    Port 22

# 定义目标机
Host 55.66.77.88
    HostName 55.66.77.88
    # 表示通过jump这个跳板机来传送
    ProxyJump jump

在ssh配置文件中定义跳板机以及跳转的目标机后,前面那个命令就可以把-e参数删掉,变成这样(简单多了)

# 上传
rsync -azP ./rsync1/test_from_rsync1 [email protected]:~/rsynctest/

# 下载
rsync -azP [email protected]:~/rsynctest/test_from_rsync1 ./rsync1/

免密码穿越跳板机

前面穿越跳板机可能要输入密码,要免密穿越跳板机,与ssh一样,只要满足“本地对跳板机ssh免密”及“本地对目标机ssh免密”,那么rsync通过跳板机传送文件就能免密,而跳板机对目标机是不要求免密的。

举例:A是你的电脑、B是跳板机、C是你要登录的目标服务器,那么只要A能免密登录到B、A能免密登录到C,则A能通过B免密登录到C,注意这里不要求B登录C免密。

ssh免密配置方法请看:Linux-使用ssh免密码登录

当然用expect应该也可以,但是需要自己编写命令,这个我也没有做过,就不在这里说了,Linux-使用ssh免密码登录有说到expect的。

如何排除文件

有时候我需要把一个文件夹的文件同步到另一个文件夹,但是有其中几个文件(夹)不想同步,这时候就要排除掉它们。


排除单个文件:不同步/path/to/test1/中的aa.txt文件到/path/to/test2/

rsync -azPru --exclude 'aa.txt' /path/to/test1/ /path/to/test2/

排除整个文件夹:不同步/path/to/test1/中的sub-test1文件夹到/path/to/test2/

rsync -azPru --exclude 'sub-test1' /Users/bruce/Code/test1/ /Users/bruce/Code/test2/

排除文件夹中的所有文件:会同步/path/to/test1/中的sub-test1文件夹到/path/to/test2/中,但sub-test1文件夹下的所有文件都不会被同步(相当于只同步了个空文件夹)

rsync -azPru --exclude 'sub-test1/*' /Users/bruce/Code/test1/ /Users/bruce/Code/test2/

一个命令中可使用多个--exclude:相当于把前面的排除单个文件夹和排除文件夹中的所有文件合在一起了

rsync -azPru --exclude 'aa.txt' --exclude='sub-test1/*' /Users/bruce/Code/test1/ /Users/bruce/Code/test2/

多个--exclude可合并为一个:只需要把它们的值放到花括号中即可

rsync -azPru --exclude={'aa.txt','sub-test1/*'} /Users/bruce/Code/test1/ /Users/bruce/Code/test2/

花括号中的内容可写到文件中:如果要排除的文件比较多,可以把上边花括号中的内容写到一个文件中(每个规则一行)

aa.txt
sub-test1/*

然后再使用--exclude-from=/path/to/exclude-list.txt来引用这个文件

rsync -azPru --exclude-from='/path/to/exclude-list.txt' /Users/bruce/Code/test1/ /Users/bruce/Code/test2/

网站测试版同步到正式版

网站经常会有测试版和正式版,我们可以把测试版加上git版本管理,更新代码时,都从git仓库更新到测试版,测试版测试没问题,再使用rsync同步到到正式版。

把以下命令保存为sync.sh,然后给它加个755可执行权限

#/usr/bin/env bash

rsync -a --out-format="%n" --log-file="rsync.txt" --exclude-from='exclude-list.txt' /wwwroot/www-test.xiebruce.top/ /wwwroot/www.xiebruce.top/
  • exclude-list.txt文件是用来排除不同步的文件,比如.[a-zA-Z0-9]*用于排除.开头的文件
.[a-zA-Z0-9]*
runtime/*
CRMEB-BZ v4.4.0(20220201).zip
.env
.gitignore
.htaccess
.travis
.version
public/upgrade
public/uploads/*
public/.user.ini
  • rsync.txt为记录同步过程的日志文件;
  • --log-file--exclude-from指定的都是文件,所以如果你指定的文件不在当前目录下,也可以写成绝对路径,如--exclude-from='/wwwroot/exclude-list.txt'
  • --out-format="%n"用于输出同步了哪些文件,通过管道符可以把它传给其它命令使用(如果你要对这些文件进行某些操作的话),关于输出同步文件列表,具体可以看:rsync输出同步的文件列表

注意:我们一般以普通用户登录服务器,但是项目文件夹权限(包括我们创建的sync.sh同步命令)一般都是www:www(或www-data:www-data),所以我们使用./sync.sh执行命令同步时,是无法同步的,因为没有权限,所以需要添加sudo,即sudo ./sync.sh,请放心,这样同步的文件,它在测试文件夹中的是属于www:www,那么同步过去之后,一样是属于www:www,所以我们不需要担心同步过去还要修改权限的问题。

使用ipv6报错问题

由于ipv6地址是使用冒号:分隔的,而我们的scp在ip后面指定路径时,也是用冒号:分隔,这就会造成混淆,所以我们要用方括号括住ipv6地址,并且要用冒号括住整个ip地址和文件路径。

具体写法如下

rsync -azPrh xiebruce@"[2700:1d13:5cd:1400:e1d2:2f98:6aec:b1c3]:/home/xiebruce/file1.txt" ./

rsync输出同步文件列表的方式

方式一

使用--info=NAME选项(只有rsync 3.1.0及以上版本才有该选项)

rsync -azPrui --info=NAME /path/from/source/ /path/to/destination/

use rsync --info=help to get the value list of --info

Use OPT or OPT1 for level 1 output, OPT2 for level 2, etc.; OPT0 silences.

BACKUP     Mention files backed up
COPY       Mention files copied locally on the receiving side
DEL        Mention deletions on the receiving side
FLIST      Mention file-list receiving/sending (levels 1-2)
MISC       Mention miscellaneous information (levels 1-2)
MOUNT      Mention mounts that were found or skipped
NAME       Mention 1) updated file/dir names, 2) unchanged names
PROGRESS   Mention 1) per-file progress or 2) total transfer progress
REMOVE     Mention files removed on the sending side
SKIP       Mention files that are skipped due to options used
STATS      Mention statistics at end of run (levels 1-3)
SYMSAFE    Mention symlinks that are unsafe

ALL        Set all --info options (e.g. all4)
NONE       Silence all --info options (same as all0)
HELP       Output this help message

Options added for each increase in verbose level:
1) COPY,DEL,FLIST,MISC,NAME,STATS,SYMSAFE
2) BACKUP,MISC2,MOUNT,NAME2,REMOVE,SKIP

方式二

使用-i选项(所有版本都能用,只不过需要使用awk把文件名从-i输出的内容中过滤出来)

rsync -azPrui /Users/bruce/Code/test1/ /Users/bruce/Code/test2/ | awk '/>f+++++++|>f.st......./{print $2}'

方式三

使用--out-format="%n"选项(所有版本适用,事实上,前面的--info-i都是基于--out-format的)

rsync -azru --out-format="%n"  /Users/bruce/Code/test1/ /Users/bruce/Code/test2/

如果要查看所有--out-format的格式,可以使用man rsyncd.conf命令查看rsyncd.conf的手册,在里面搜索log format就可以搜索到


rsync的选项很多,我只是说了几个我用到的,其它的可以自己man rsyncrsync -h查询。

打赏

订阅评论
提醒
guest

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x

扫码在手机查看
iPhone请用自带相机扫
安卓用UC/QQ浏览器扫

使用rsync代替scp上传文件到服务器或从服务器下载文件(支持跨越跳板机)