Linux下使用Expect远程执行shell命令和脚本

摘自:http://blog.zheezes.com/expect-remote-execution-under-linux-using-shell-commands-and-scripts.html

 

有几十台Linux服务器都要执行一组相同的操作,一台一台的登录上去执行不现实,只能是软件自动化的操作,而ssh本身是交互的,无法通过管道的方式进行输入,这就需要借助Tcl脚本和Expert两个工具了。

Tcl(Tool Command Language),类似于python,也是一种跨平台的脚本语言,不过有自己的语法,这里使用的的原因是,TclExpect工具的基础。

Expect,是Unix/Linux中用来进行自动化控制和测试的软件工具,由Don Libes制作,作为Tcl脚本语言的一个扩展,应用在交互式软件中如telnetftpPasswdfsckrlogintipssh等等。简单的说,Expect可以通过编程模拟人与ssh的交互。

Expect脚本的编写使用比较麻烦,所以下面的脚本将Expect命令封装到shell函数中,对使用者来说,在环境中安装好Expect工具,然后直接调用shell函数就好了。

make_tmp_filemake_rand_file是辅助的函数,用于生成临时文件。exec_script用于远程执行脚本,参数为主机的ip端口用户密码和要执行的脚本,exec_cmd用于远程执行命令,用于一行就能执行完的命令,注意timeout等可选参数。

最新最完整的shell脚本,附送大量超赞shell函数,你值得拥有gear.sh

 functionmake_tmp_file()

{
     local name = $ { 1 : - "rand" }
     local magic = ` date + % s `
     echo "/tmp/__${magic}__${name}"
}
 
function make_rand_file ( )
{
     make_tmp _file "$*"
}
 
# int exec_script(host, port, user, passwd, script, [timeout = 86400])
# 0, succ
# 1, fail
# 2, invalid params
# 3, fail
# 4, invalid script
# 5, login fail
# 6, put file fail
# 7, timeout
# 8, remote execute script fail
function exec_script ( )
{
     if [ $ # -lt 5 ]; then
         return 2
     fi
 
     local host = $ 1
     local port = $ 2
     local user = $ 3
     local passwd = $ 4
     local script = $ 5
     local timeout = $ ( ( $ { 6 : - 86400 } ) ) # default 1 day
     local rscp = $ ( make_rand _file ` basename $script ` )
     local ret = 0
 
     if [ ! - f $script ] ; then
         return 4
     fi
 
     echo "script = ${script}, remote_script = ${rscp}"
     ssh _put $host $port $user $passwd $script $rscp
 
     expect - c"
         set timeout $timeout
         set flag 0
         spawn ssh $user @ $host ;
         expect {
             \" * assword * \" { send $passwd \ r ; }
             \" yes \ / no ) ? \" {
                 set flag 1 ;
                 send yes \ r ;
             }
             \" Welcome \" { }
         }
         if { \ $flag == 1 } {
             expect {
                 \" * assword \" {
                     send $passwd \ r ;
                 }
             }
         }
         expect {
             \" * assword * \" {
                 puts \" INVALID PASSWD , host = $host , user = $user , passwd = $passwd \" ;
                 exit 1
             }
             \" #\ \" {} \"$\ \" {} \">\ \" {}
         }
         send $rscp \ r ;
         expect {
             \" #\ \" {} \"$\ \" {} \">\ \" {}
         }
         send \" rm - f $rscp \ r \"
         send exit \ r ;
         expect eof {
             exit 0
         }
    "
     ret = $ ?
     if [ $ret - ne 0 ] ; then
         return 5
     fi
 
     return 0
}
 
# int exec_cmd(host, port, user, passwd, cmd, [timeout = 86400], [rfile = /dev/null])
# 0, succ
# 1, fail
# 2, invalid params
# 3, fail
# 4, invalid script
# 5, login fail
# 6, put file fail
# 7, timeout
# 8, remote execute script fail
function exec_cmd ( )
{
     if [ $ # -lt 5 ]; then
         return 4
     fi
 
     local host = $ 1
     local port = $ 2
     local user = $ 3
     local passwd = $ 4
     local cmd = $ 5
     local timeout = $ ( ( $ { 6 : - 86400 } ) ) # default 1 day
     local rfile = $ { 7 - "/dev/null" }
     #local log=$(make_tmp_file "${__GEAR_SH}_exec_cmd")
     local ret = 0
 
     expect - c"
         set timeout $timeout
         set flag 0
         spawn ssh $user @ $host ;
         expect {
             \" * assword * \" { send $passwd \ r ; }
             \" yes \ / no ) ? \" {
                 set flag 1 ;
                 send yes \ r ;
             }
             \" Welcome \" { }
         }
         if { \ $flag == 1 } {
             expect {
                 \" * assword \" {
                     send $passwd \ r ;
                 }
             }
         }
         expect {
             \" * assword * \" {
                 puts \" INVALID PASSWD , host = $host , user = $user , passwd = $passwd \" ;
                 exit 1
             }
             \" #\ \" {} \"$\ \" {} \">\ \" {}
         }
         log_file $ { rfile }
         send \" $cmd \ r \" ;
         expect {
             \" #\ \" {} \"$\ \" {} \">\ \" {}
         }
         send exit \ r ;
         expect eof {
             exit 0
         }
    "
     cat $ { rfile } | sed - n '1,/[#$>].*exit/p' | sed '1d;$d' > $ { rfile }
     #if [ -f ${log} ]; then rm ${log}; fi
     ret = $ ?
     if [ $ret - ne 0 ] ; then
         return 5
     fi
 
     return 0
}

猜你喜欢

转载自lbwahoo.iteye.com/blog/2097442