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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步