Always keep a |

南哈哈

园龄:3年10个月粉丝:2关注:0

Shell expect

使用场景

expect介绍

示例

 

使用场景:

在进行命令行操作时,会遇到一些命令执行的中途需要手动输入。比如使用git 克隆、上传、下载命令中需要输入账号与密码,比如执行远程拷贝需要输入密码等。

以上场景日常使用频率过高,每次输入内容高度一致,可使用expect交互命令,把账号密码保存到脚本中,每次执行脚本,让脚本自动输入,减少手动负担

 

expect介绍

expect是一个免费的编程工具,用来实现自动的交互式任务,而无需人为干预。说白了expect就是一套用来实现自动交互功能的软件需要自行安装

yum install -y expect

expect基础

在使用expect时,基本上都是和以下四个命令打交道:

命令 作用
spawn 启动新的进程
expect 从进程接收字符串,信息匹配成功则执行expect后面的程序动作
send 用于向进程发送字符串
interact 允许用户交互,与expect eof作用类似,但结束交互后,所处位置为脚本内最后所在位置
set  定义变量
set timeout  设置超时时间
exp_continue  相当于其他语言的continue,此处用于判断语句,在此处重新进行判断
expect eof 表示结束交互,但会原终端所在位置。
exit  退出expect脚本
  • spawn 命令用来启动新的进程,spawn后的expect和send命令都是和使用spawn启动的新进程进行交互。
  • expect 通常用来等待一个进程的反馈,我们根据进程的反馈,再使用send命令发送对应的交互命令。
  • send 命令接收一个字符串参数,并将该参数发送到进程。
  • interact 命令用的其实不是很多,一般情况下使用spawn、expect和send命令旧可以很好的完成我们的任务;但是在一些特殊场合下还是需要使用interact命令的,interact命令主要用于退出自动化,进入人工交互。比如我们使用spawn、send和expect命令完成了ssh登录south主机,但是我们希望登录成功后,仍然可以停留在south主机命令行状态,以便手动的执行后续命令,此时使用interact命令就可以很好的完成这个任务。

 

总结expect自动应答的基本步骤

第一步: 运行一个程序或命令=> spawn 命令信息
第二步: 识别产生信息关键字=> expect 捕获关键字 {send 应答信息}
第三步: 根据识别关键做处理=> send 应答信息
expect实现ssh非交互登录
#!/usr/bin/expect
# expect脚本,需要使用expect $0 方式执行
# 开启一个新的会话
spawn ssh south@192.168.128.200
# 期望出现什么
# send 发送一个信息
# exp_continue 如果没有yes/no 则跳过
expect {
"yes/no" { send "yes\r"; exp_continue } # \r 回车`man tr`
"password" { send "123456\r" };
}
# 停在新会话中,不输入会再次回到旧会话
interact
[root@nan ~]# expect expect01.expect
spawn ssh south@192.168.128.200
The authenticity of host '192.168.128.200 (192.168.128.200)' can't be established.
ECDSA key fingerprint is SHA256:gUWWp+3dSGCUjHZIWfCsCO0X3lsDo9Yl/ZUY9qRqQ34.
ECDSA key fingerprint is MD5:1c:3b:ac:14:d9:86:66:ca:fa:2c:9e:c1:68:eb:68:45.
Are you sure you want to continue connecting (yes/no)? yes # 非交互输入yes
Warning: Permanently added '192.168.128.200' (ECDSA) to the list of known hosts.
south@192.168.128.200's password: # 非交互输入密码
Last login: Mon Jun 13 12:14:44 2022 from 192.168.128.200
[south@nan ~]$

设置变量

#!/usr/bin/expect
# expect脚本,需要使用expect $0 方式执行
# 设置变量
set ip 192.168.128.200
set user south
set passwd 123456
# 设置超时时间
set timeout 5
# 开启一个新的会话
spawn ssh ${user}@${ip}
# 期望出现什么
# send 发送一个信息
# exp_continue 如果没有yes/no 则跳过
expect {
"yes/no" { send "yes\r"; exp_continue } # \r 回车`man tr`
"password" { send "${passwd}\r" };
}
# 停在新会话中,不输入会再次回到旧会话
interact

设置变量

#!/usr/bin/expect
# expect脚本,需要使用expect $0 方式执行
# 设置变量
# 设置位置参数,相当于shell中的$1
set ip [lindex $argv 0]
set user [lindex $argv 1]
set passwd 123456
# 设置超时时间
set timeout 5
# 开启一个新的会话
spawn ssh ${user}@${ip}
# 期望出现什么
# send 发送一个信息
# exp_continue 如果没有yes/no 则跳过
expect {
"yes/no" { send "yes\r"; exp_continue } # \r 回车`man tr`
"password" { send "${passwd}\r" };
}
# 停在新会话中,不输入会再次回到旧会话
#interact
# 出现 '#' 号,执行以下命令
expect "#"
send "useradd nanaaa\r"
send "pwd\r"
send "exit\r"
# 结束交互
expect eof
expect expect03.expect 192.168.128.200 south

 scp非交互传输文件

#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set passwd 123456
set timeout 5
spawn scp /etc/hosts ${user}@${ip}:/tmp
expect {
"yes/no" { send "yes\r"; exp_continue }
"password" { send "${passwd}\r" };
}
expect eof

实现批量主机公钥推送

#!/bin/bash
> ip.txt
rpm -q expect
if [ $? -ne 0 ];then
yum -y install expect
fi
if [ ! -f ~/.ssh/id_rsa ];then
ssh-keygen -P "" -f ~/.ssh/id_rsa
fi
for i in 180
do
{
IP=192.168.128.180
ping -c1 $IP &>/dev/null
if [ $? -eq 0 ];then
echo "$IP is up..." | tee -a ip.txt
/usr/bin/expect <<-EOF
spawn ssh-copy-id root@192.168.128.180
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "123456\r" }
}
expect eof
EOF
fi
}&
done
wait
echo "finish....."
注意:ssh-copy-id 后的IP 必须满足输入yes和password两个条件,否则会导致spawn会话没有被成功开启
报错:
expect: spawn id exp6 not open
while executing
"expect eof"

 

本文作者:南哈哈

本文链接:https://www.cnblogs.com/nanruosen/p/16370210.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   南哈哈  阅读(314)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起