摘自: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等可选参数。
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
}