转自:http://blog.csdn.net/napolunyishi/article/details/18219867
这两天做了一个需求,因为上一个版本的/tmp空间默认只分配了5G,而升级程序上传解压路径也是/tmp,且解压过程要占用5G左右的空间,这样 就导致/tmp空间占满,解压失败,升级无法进行。后来想了一个办法,就是从/var建了一个软链接到/tmp,这样实际上升级文件上传解压到/var路 径下了,解决了/tmp路径空间不足的问题。但是因为客户那里是一个cluster环境,由6个node组成,最好能够在一个机器上执行一次补丁,所有 node都生效。
经过几次尝试,写了两个shell脚本,一个run.sh负责调度和分发补丁,另外一个doFix.sh,真正给系统打补丁的脚本。这里只介绍调度分发的部分
基本思路就是从主node上将doFix.sh脚本分发到其他各个node上,然后再从主node上ssh到各node执行补丁脚本。
调度脚本run.sh:
#!/bin/bash #check version cat /etc/issue | grep "V3.5" if [ $? -ne 0 ]; then echo "This is not V3.5, exit!" exit fi ISFABRIC=0 ADMPW="" echo read -rsn1 -p "Is this a fabric with same admin password? [y/n]" echo if [ "$REPLY" = "y" -o "$REPLY" = "Y" ]; then ISFABRIC=1 read -esp "Please input the password: " ADMPW else echo "Please run the script doFix.sh manually" exit fi echo echo echo "Patch current node..." sh ./doFix.sh NODEIP=$(ifconfig eth0 | grep 'inet addr' | cut -d':' -f2 | awk '{print $1}') echo "Begin to patch other nodes..." echo egrep "MAGICNODE-" /etc/hosts | awk '{print $1}' | sort | uniq | while read LINE do if [ "$NODEIP" = "$LINE" ]; then continue fi echo "Patching node $LINE" # scp doFix.sh to remote node ./scpExpect $ADMPW./doFix.sh admin@$LINE:/tmp/ if [ $? -ne 0 ]; then echo "SCP script to node $LINE failed! skip" continue fi # execute patch script ./sshExpectSudo admin $ADMPW $LINE "sudo bash /tmp/doFix.sh" if [ $? -ne 0 ]; then echo "Remote patch node $LINE failed! skip" continue fi echo echo done echo "Patch finished."
从/etc/hosts文件中获取cluster环境的所有node IP,然后将doFix.sh脚本通过scp送过去,再执行ssh打补丁。
这里两个关键点是scpExpect和sshExpect,何为Expect文件?请参考http://expect.sourceforge.net/,网上有很多Expect的介绍文章,归结一句话就是一种实现自动化交互的脚本语言,从TCL扩展出来。
scpExpect
#!/usr/bin/expect -f # usage: scpExpect user password ip file target system "rm -rf ~/.ssh/known_hosts" set password [lindex $argv 0] set from [lindex $argv 1] set to [lindex $argv 2] set timeout 120 # now connect to remote UNIX box (ipaddr) with given script to execute spawn scp -r -o StrictHostKeyChecking=no $from $to match_max 100000 expect { "*assword:*" { send -- "$password\r" set timeout -1 expect { "*assword:*" { exit } } } "yes/no)?" { send "yes\r" set timeout -1 } -re . { exp_continue } timeout { exit } eof { exit } }
sshExpect
#!/usr/bin/expect -f # usage: ssh user password ipaddre command target # set Variables set user [lrange $argv 0 0] set password [lrange $argv 1 1] set ipaddr [lrange $argv 2 2] set command [lrange $argv 3 3] set target [lrange $argv 4 4] set timeout -1 # now connect to remote UNIX box (ipaddr) with given script to execute spawn ssh -o StrictHostKeyChecking=no $user@$ipaddr $command $target match_max 100000 # Look for passwod prompt expect "*?assword:*" # Send password aka $password send -- "$password\r" # send blank line (\r) to make sure we get back to gui send -- "\r" expect eof