18.8 使用netcat备份
netcat被誉为网络工具中的“瑞士军刀”,体积虽小但是功能强大。netcat最简单的功能是用于端口扫描,下面的示例将针对指定IP地址的20~25端口进行扫描,可以看到21(ftp)、22(ssh)端口是打开的。
- [root@localhost ~]# nc -z -v -n 192.168.61.131 20-25
nc: connect to 192.168.61.131 port 20 (tcp) failed: Connection refused
Connection to 192.168.61.131 21 port [tcp/*] succeeded!
Connection to 192.168.61.131 22 port [tcp/*] succeeded!
nc: connect to 192.168.61.131 port 23 (tcp) failed: Connection refused
nc: connect to 192.168.61.131 port 24 (tcp) failed: Connection refused
nc: connect to 192.168.61.131 port 25 (tcp) failed: Connection refused
除了端口扫描外,netcat还有通过网络传输文件的功能,它能通过TCP或UDP协议在网络中读写数据。简单来说,netcat所做的就是在两台服务器之间建立连接并交流数据,这种功能很容易让我们想到可以利用netcat通过网络备份数据。虽然在Linux下有很多传输文件的方法,比如SCP、FTP、SMB、NFS等,但是netcat在和其他小工具结合后,可拥有更为灵活的功能。比如与tar命令结合,可以在压缩解压的同时传输文件;与mcrypt结合,可以一边加密解密一边传输文件;与mplayer命令结合,可以在接收数据的同时播放视频;与dd结合,可以在dump文件的同时保存到远端,等等。
在备份文件较大的情况下,典型的备份过程是先使用工具压缩打包源文件,该步骤耗时Time1;完成此操作后,为了数据安全,会将生成的压缩文件同时复制到远端某个服务器集中存放,该步骤耗时Time2,则整个过程耗时为X=Time1+Time2。如果需要备份的文件特别大,网络质量也不是很好,整体耗时X会显著增加。
来做一个简单的计算:笔者测试了运行在VMware上的虚拟机的磁盘I/O速度(宿主机是某品牌的SSD磁盘),在以8KB为单次I/O的同时读写的速度为40MB/s(注意:在实际生成环境下,由于服务器还有其他业务负载,而且SSD硬盘目前成本较高,在服务器端还没有形成大规模部署,所以数据不会这么乐观),30秒内完成了1.2GB的数据读写,粗略计算完成120GB的数据打包操作需耗时50分钟。按照文件压缩比为25%计算,生成的压缩文件为30GB,通过百兆局域网复制耗时约为41分钟(注意:广域网的网络质量会明显比百兆局域网的网络质量差),所以整体耗时91分钟。同样的备份场景,如果使用tar命令,在打包的同时通过管道给netcat,经由netcat传输到远端备份服务器。由于打包和传输过程从线行变为了并行,所以整体耗时将会降低到50分钟,时间占比降低了45%,效果非常显著。示例如下:
#
基于VMware
上一台虚拟机的磁盘I/O
性能(宿主机使用某品牌SSD
硬盘)
[root@localhost ~]# dd if=/dev/sda of=/tmp/RW.img bs=8k
151935+0 records in
151935+0 records out
1244651520 bytes (1.2 GB) copied, 30.8994 seconds, 40.3 MB/s
#
国内某云主机的磁盘I/O
性能
[root@localhost ~]# dd if=/dev/sda of=/tmp/RW.img bs=8k
98663+0 records in
98663+0 records out
808247296 bytes (808 MB) copied, 31.5515 seconds, 25.6 MB/s
现在来了解一下netcat实现文件传输的方法。首先,依次在两台服务器上安装nc工具。
- [root@localhost ~]# yum install nc
然后,使用nc命令在文件接收服务器(又称服务端)绑定一个端口,该命令在服务器B上执行。
#
指定绑定本地端口1234
,其实就是创建了一个socket
端口
#
读者可以任意使用一个未被占用的端口,建议大于1024
#
这条命令的含义是:监听本地1234
端口,并将在该端口上收到的数据保存到file.rec
文件中
[root@localhost ~]# nc -l 1234 > file.rec &
最后,在发送文件的服务器上(又称客户端,此处是服务器A)向这个网络socket中发送数据。可采取下面任意一种方式:
- #cat
本地文件install.log
,输出内容通过管道重定向到网络socket
中
[root@localhost ~]# cat install.log | nc 192.168.61.131 1234
#
下面的命令和上面的等价
#[root@localhost ~]# nc 192.168.61.131 1234 < install.log
读者到服务器B上查看一下file.rec文件,会发现,其内容和服务器A上的install.log是完全一致的。当然了,file.rec就是install.log的一个网络拷贝!
实际上,不仅是文本文件,其他类型的文件甚至是磁盘分区都可以通过这种方式传输。下面的例子演示使用netcat传送二进制内核文件。要说明的是,一旦服务端在监听端口上完成了数据接收,就会自动关闭该端口,所以服务端每次接收数据都需要重新绑定端口。
#
发送服务器B
的vmlinuz-2.6.18-194.el5
文件到服务器A
(二进制类型)
#
服务器A
上运行
[root@localhost ~]# nc -l 1234 > kernel.rec &
#
服务器B
上运行
[root@localhost ~]# nc 192.168.61.131 1234 < bootvmlinuz-2.6.18-194.el5
#
发送服务器B
的sda1
分区到服务器A
#
服务器A
上运行
[root@localhost ~]# nc -l 1234 | dd of=./sda1.img
208763+41 records in
208782+0 records out
106896384 bytes (107 MB) copied, 12.4768 seconds, 8.6 MB/s
#
服务器B
上运行
[root@localhost ~]# dd if=/dev/sda1 | nc 192.168.61.131 1234
208782+0 records in
208782+0 records out
106896384 bytes (107 MB) copied, 7.82997 seconds, 13.7 MB/s
从上面的例子可以看到,通过netcat传输文件需要服务端(接收端)和客户端(发送端)协同工作,而且必须要服务端先打开监听端口,然后才能从客户端发送文件。所以如果是例行性地文件传送,就需要用到crontab,并且要故意设置一定的时间差来协调这种备份。
现有两台服务器,分别是服务器A(192.168.61.130)、服务器B(192.168.61.131),需求是每天把服务器A的整个/root目录打包备份到服务器B的rootbackup目录中,并以日期和时间戳作为后缀进行归档,以方便日后查找。下面在服务器B上创建以下脚本给予执行权限,并创建crontab任务。
- [root@localhost ~]# cat server01.sh
#!/bin/bash
NC=/usr/bin/nc
TIMESTAMP=`date +%Y%m%d%H%M%S`
PORT=1234
$NC -l $PORT > root.$TIMESTAMP.tgz
[root@localhost ~]# chmod +x server01.sh
#
创建计划任务如下,每天凌晨1
点打开端口准备接收备份数据
[root@localhost ~]# crontab -l
0 1 * rootserver01.sh
在服务器A上创建以下脚本并给予执行权限,并创建crontab任务。
- [root@localhost ~]# cat client01.sh
#!/bin/bash
NC=/usr/bin/nc
TAR=/bin/tar
BACKUP_DIR=/root
PORT=1234
SERVER_IP=192.168.61.131
$TAR -zvcf - $BACKUP_DIR | nc $SERVER_IP $PORT
[root@localhost ~]# chmod +x client01.sh
#
创建计划任务如下,每天凌晨1
点01
分开始向服务器传送备份数据
[root@localhost ~]# crontab -l
1 1 * rootclient01.sh
建议读者先在服务端和客户端手工运行一下脚本,确保脚本本身工作正常后再使用系统计划任务执行。另外,请注意两台服务器的时间一定要正确同步。