假设有100多台服务器,里面都有个同名目录/var/business_log,里面存放的业务数据日志文件,现在每天需要汇总这些日志文件并进行数据统计和分析。
目前提供的信息有:
1. 100多台服务器的ip、账号、密码、端口
2. 一台主服务器,用于分析日志文件的业务数据。
我们要做的事情,就是每天将100多台服务器前一天的数据拷贝到主服务器,然后再进行日志数据统计和分析。
最终确定的解决方案:
在主服务器依次访问100多台服务器,通过rsync同步命令获取日志数据
1. bash脚本如何获取命令行里的参数
2.使用rsync同步命令时,如何自动输入验证密码
3.bash脚本里的变量,如何传递进入expect
4.rsync同步进程中断,该如何自动继续
5.如何判定100多台服务器里每台每天的数据拷贝成功
下面就围绕上面几个技术点进行展开。
我用的最简单的方式,直接在执行的脚本后带上参数即可,每个参数用空格分隔开。
例如下面这样:
/home/fetch_log.sh xxx.xxx.xxx.xxx 22 password logsize
然后在bash脚本里就按如下方式获取:
#服务器ip、端口、密码及日志文件大小 serverIp=$1 serverPort=$2 serverPass=$3 logSize=$4
expect 工具就是为了解决一些命令执行后需要与人进行互动操作的问题。
例如需要用户输入yes或no才进行下一步操作的。
用法也很简单,就记住spawn expect send命令分别是干嘛的就OK了。
先直接上一段代码,再来讲解吧。
serverIp=$serverIp serverPort=$serverPort serverPass=$serverPass logSize=$logSize /usr/bin/expect <<EOF spawn rsync -avzP -e "ssh -p $env(serverPort)" --exclude error.log root@$env(serverIp):/var/business_log/ /data/logs/ expect { "(yes/no)" { send "yes\r" expect "*assword:" {send "$password\r"} } "password" { send "$password\r" } } expect eof EOF
EOF之间的代码块,就属于expect工作区。
在expect工作区里执行shell命令,头部就需要使用spawn命令。
所以,同理,如果想在expect工作区里看serverIp变量,就在echo前面带上spawn就好了。
spawn echo $env(serverIp)
接下来的expect就是指定指定执行命令会弹出的提示,这里提示可以不用完全照搬,只需要有关键字即可。
比如第一次执行rsync命令进行跨服务器拷贝时,会弹出如下提示:
The authenticity of host '120.79.176.238 (120.79.176.238)' can't be established. RSA key fingerprint is a7:0d:51:eb:95:22:7b:18:43:91:89:9a:09:3b:cd:33. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '120.79.176.238' (RSA) to the list of known hosts. root@120.79.176.238's password:
其中
Are you sure you want to continue connecting (yes/no)
正好匹配expect块里的“yes/no”这部分,后面send命令就代替人工输入yes。
上面之所以写两个匹配规则,是因为第一次连接新服务器时,会提示上面是否连接的提示,第二次连接时,就没有这个提示了,而是直接提示输入密码,也就是走的上面代码里expect对应的“password”这块(注意不是“yes/no”里的password)。
看第2步骤中的代码,我想你应该注意到了这个问题。
在expect区块里,如何使用外部bash脚本里的变量,就看如下两个部分:
serverIp=$serverIp serverPort=$serverPort serverPass=$serverPass logSize=$logSize /usr/bin/expect <<EOF $env(serverPort)
其中第一部分,突然感觉似乎没有必要,我明天再次确认下。
第二部分,就是expect区块里变量引用方式,通过${serverPort}这种方式会报错,${serverPort}是bash脚本里变量使用方式。
待续
待续