一、概述
我们通过Shell可以实现简单的控制流功能,如:循环、判断等。但是对于需要交互的场合则必须通过人工来干预,有时候我们可能会需要实现和交互程序如telnet服务器等进行交互的功能。而expect就使用来实现这种功能的工具。
安装expect
yum -y install expect
四个命令
Expect中最关键的四个命令是send,expect,spawn,interact
send:用于向进程发送字符串
expect:从进程接收字符串
spawn:启动新的进程,执行命令
interact:允许用户交互
二、实例
在使用ansible时,需要进行ssh互信认证,及ansible操作端服务器需要免密登录其他被控制端服务器。
如果服务器太多,一个一个输入账户密码就特别繁琐了,此时可以通过expect脚本完成交互式操作。
1.先将需要免密登录的远程服务器IP写入到hosts.txt文件,方便后续脚本调用
2.编写脚本如下:
注:复制执行脚本时把中文注释去掉,否则会有问题
#!/usr/bin/expect set timeout -1 #设置超时时间,永不超时 set username danny #设置SSH用户名 set password danny123 #设置密码 set hosts [open hosts.txt r] #以只读的方式将hosts.txt中的值赋值给hosts参数 while { [gets $hosts IP] >= 0 } { spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $username@$IP #spawn启动脚本或命令的会话,以衍生子进程的方式来运行。 expect { "yes/no" {send "yes\r"; exp_continue} #交互式操作,输入yes再回车 "password:" {send "${password}\r"} #输入密码,回车 } expect eof
#子进程运行完成之后,会得到标识子进程已经结束的eof字符,脚本结束(和spawn对应,当spawn发送指令到终端执行,在返回时被expect捕捉时,在起始会有一个eof标识字符) } close $hosts
执行(不要用sh auto_ssh.sh执行,这是expect脚本,会报格式错误)
./auto_ssh.sh
附两个远程上传脚本示例:
脚本1、
#!/usr/bin/expect set username danny set password danny123 set port 21435 set host 192.168.1.10 set argv [lindex $argv 0] set timeout -1 spawn scp -P $port -o StrictHostKeyChecking=no -r $argv $username@$host:/home/danny expect "password:" send "$password\r" expect eof exit
执行:
./auto_scp.sh xxx.tar.gz
脚本2::
#!/bin/bash cd /root/product/ auto_smart_scp () { expect -c "set timeout -1; spawn scp $@; expect { *assword:* {send $pass\r; expect { *denied* {exit 2;} eof } } eof {exit 1;} } " return $? } pass='danny123' auto_smart_scp -P 21435 -o StrictHostKeyChecking=no -r $1 root@192.168.1.10:/root/temp
执行
sh auto_scp.sh xxx.tar.gz