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

JavaLab 2014-07-28

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

 

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

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

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

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

make_tmp_file和make_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}"
}
 
functionmake_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
functionexec_script()
{
    if[$# -lt 5 ]; then
        return2
    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
        return4
    fi
 
    echo"script = ${script}, remote_script = ${rscp}"
    ssh_put$host$port$user$passwd$script$rscp
 
    expect-c"
        set timeout$timeout
        set flag0
        spawn ssh$user@$host;
        expect{
            \"*assword*\"{send$passwd\r;}
            \"yes\/no)?\"{
                set flag1;
                send yes\r;
            }
            \"Welcome\"{}
        }
        if{\$flag==1}{
            expect{
                \"*assword\"{
                    send$passwd\r;
                }
            }
        }
        expect{
            \"*assword*\"{
                puts\"INVALID PASSWD,host=$host,user=$user,passwd=$passwd\";
                exit1
            }
            \"#\ \" {} \"$\ \" {} \">\ \" {}
        }
        send$rscp\r;
        expect{
            \"#\ \" {} \"$\ \" {} \">\ \" {}
        }
        send\"rm-f$rscp\r\"
        send exit\r;
        expecteof{
            exit0
        }
    "
    ret=$?
    if[$ret-ne0];then
        return5
    fi
 
    return0
}
 
# 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
functionexec_cmd()
{
    if[$# -lt 5 ]; then
        return4
    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 flag0
        spawn ssh$user@$host;
        expect{
            \"*assword*\"{send$passwd\r;}
            \"yes\/no)?\"{
                set flag1;
                send yes\r;
            }
            \"Welcome\"{}
        }
        if{\$flag==1}{
            expect{
                \"*assword\"{
                    send$passwd\r;
                }
            }
        }
        expect{
            \"*assword*\"{
                puts\"INVALID PASSWD,host=$host,user=$user,passwd=$passwd\";
                exit1
            }
            \"#\ \" {} \"$\ \" {} \">\ \" {}
        }
        log_file${rfile}
        send\"$cmd\r\";
        expect{
            \"#\ \" {} \"$\ \" {} \">\ \" {}
        }
        send exit\r;
        expecteof{
            exit0
        }
    "
    cat${rfile}|sed-n'1,/[#$>].*exit/p'|sed'1d;$d'>${rfile}
    #if [ -f ${log} ]; then rm ${log}; fi
    ret=$?
    if[$ret-ne0];then
        return5
    fi
 
    return0
}

相关推荐