在linux平台上常用rsync协议来同步文件和目录,’rsync’也是各种linux发行版标配的命令。当我们基于linux平台开发应用程序时,常常需要从Java或者Python代码中调用rsync命令来实现文件的传输。
例如,假设我们要按照如下需求来传输文件:
- 有两台机器:localhost和remotehost
- Java程序deploy在localhost上,通过rsync将本机文件传送到remotehost,或者从remotehost pull文件到localhost
- rsync通过ssh连接remotehost
- 在remotehost有个叫test的帐户,专门用来rsync传输文件,只能用密钥文件登陆
- 最重要的是,在rsync连接过程中不需要输入test的帐户密码,否则密码输入界面会block住Java程序的运行
要实现rsync的无密码传输,基本思路是用一对公私钥来代替帐户密码,实现ssh连接时的认证。
下面我们来看看一步步如何实现。
配置rsync
1. [远端机器] 创建专用帐户test
1 2 3 4 5 6 7 8 9 |
# 创建用户组test $ groupadd -g 1212 test # 创建test用户,并加入test用户组 $ useradd -m -s /bin/bash -g 1212 -u 1212 test # 为test创建.ssh目录 $ mkdir /home/test/.ssh $ chown test:test /home/test/.ssh |
注意:
- gid和uid均为1212,此为示例,也可以选用其它值,只要保证不和现有的用户和组冲突
- “-m”表示要为test用户创建home目录,即/home/test/
2. [本地机器] 用ssh-keygen生成密钥
1 2 3 4 5 6 7 |
[root@xxxx ~]$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): /usr/rsync_id_dsa Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /usr/rsync_id_dsa. Your public key has been saved in /usr/rsync_id_dsa.pub. |
注意:
- 在提示输入key file path时,为避免覆盖已有的root帐户的id_rsa文件,将其存储到/usr/rsync_id_dsa
- 在提示输入文件密码时,直接按回车,采用空密码
- 最后生成了两个文件,分别存储私钥和公钥
3. [本地机器] 将公钥传送到远端机器test帐户的.ssh目录下
1 |
$ scp /usr/rsync_id_dsa.pub root@171.69.201.209:/home/test/.ssh |
4. [远端机器] 将传输过来的公钥导入test的authorized_keys文件
1 2 3 |
$ cd /home/test/.ssh $ cat rsync_id_dsa.pub > authorized_keys $ chown test:test authorized_keys |
rsync命令
这样,我们就可以免输密码在两机器间同步文件和目录了,比如,一个最简单的命令:
1 |
$ rsync -e "ssh -i /usr/rsync_id_dsa" /tmp/testfile test@remotehost:/tmp/ |
值得注意的是,当从Java或Python代码中构建rsync命令时,有时很难将-e “ssh -i xxxx”作为一个普通的command option,这里有一个简单的替代方法,就是在启动rsync命令之前,往rsync进程中添加一个环境变量:RSYNC_RSH=”ssh -i xxxx”
上面只是一个最简单的rsync命令,其实rsync有许多有意思的选项,可以帮助我们完成很多高端大气上档次的功能。比如,下面是一个更加复杂的命令,用来在两台机器间传输整个目录并在传输完成后删除源文件:
1 |
$ rsync -e "ssh -i /usr/rsync_id_dsa" -v --progress -r -z --compress-level=9 -o -g -p --remove-source-files --temp-dir=/tmp/rsynctmpdir/ --partial-dir=/tmp/rsynctmpdir/ --delay-updates --itemize-changes --out-format=FILEDETAIL::%%n::%%l::%%i::%%M /tmp/testfolder/ test@remotehost:/tmp/testfolder/ |
具体参数的含义可参考rsync文档,这里仅作简单说明:
- -v:传输过程中打印调式信息
- –progress:传输过程中打印当前进度
- -r:递归传输所有子目录和文件
- -z, –compress-level=9:传输过程中对文件进行压缩,可提高传输效率
- -o, -g, -p:传输过程中保持文件的ownership, group和permission
- –remove-source-files:传输结束之后删除源文件。注意,在rsync 2.x中,相应的选项为–remove-sent-files
- –temp-dir, –partial-dir, –delay-updates:将源目录下所有的文件放在一个transaction里,要么全成功,要么全失败。传输过程中将文件放在temp-dir和partial-dir中,全部完成之后再移动到目标目录。这几个选项在remotehost上有其它程序需要consume传输完成之后的文件时特别有用。
- –itemize-changes, –out-format:按照指定格式输出每一个要传送的文件信息,这在应用程序需要捕获传输的文件列表时很有用。比如,应用程序仅指定在两个机器间要同步的目录(从localhost到remotehost,或者从remotehost到localhost),然后通过这两个选项就可以捕获rsync的output,过滤出相应的输出行(根据–out-format中指定的”FILEDETAIL”前缀字符串),然后就可以构建出目录下的文件列表了,比如文件名(%%n)、文件大小(%%l)等等
发表评论
要发表评论,您必须先登录。