千家信息网

shell编程之Expect免交互

发表于:2024-11-14 作者:千家信息网编辑
千家信息网最后更新 2024年11月14日,shell编程之Expect免交互一、前言​ shell脚本存在的核心意义就在于基于shell命令简化甚至省略可避免的人工操作,通过各种控制流程结构以及正则表达式等方法,逐步实现自动化操作的整个过程,
千家信息网最后更新 2024年11月14日shell编程之Expect免交互

shell编程之Expect免交互

一、前言

​ shell脚本存在的核心意义就在于基于shell命令简化甚至省略可避免的人工操作,通过各种控制流程结构以及正则表达式等方法,逐步实现自动化操作的整个过程,由此也可见,shell并没有面向对象的思想,类似C语言,毕竟C语言是操作系统或者说是内核的核心语言。

​ 所以,语言并无优劣之分,只是每个人使用的习惯与方式不同,换句话说,难易的不是语言,而是思想与突如其来的灵感。

二、Expect概述与安装

Expect概述

​ Expect是建立在TCL基础上的一个工具,Expect是用来进行自动化控制和测试的工具。主要解决shell脚本中不可交互的问题。对于大规模的Linux运维很有帮助。

​ 在Linux运维和开发中,我们经常需要远程登录服务器进行操作,登录的过程是一个交互过程,需要输入yes/no password等信息。为了模拟这种输入,可以使用Expect脚本。

Expect的安装:yum install -y expect

三、基本命令

  1. send:向进程发送字符串,用于模拟用户的输入,但不支持换行 一般需要加上 \r

  2. expect:内部命令

    ​ 判断上次输出结果里是否包含指定的字符串,有则返回,反之就等待超时时间后返回。

    ​ 只能捕捉由spawn启动的进程的输出。

  3. spawn:启动进程,并跟踪后续交互信息。

  4. interact:执行完成后保持交互状态,把控制权交给控制台。

Timeout:指定超时时间,过期则继续执行后续指令

  • 单位是s
  • timeout -1为永不超时
  • 默认情况下timeout 是10s

exp_continue--允许expect继续向下执行指令(比较关键,多次交互)

send_user--回显命令,相当于echo

四、expect语法

expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
选项
-c:从命令行执行expect脚本,默认expect是交互地执行的
示例:expect -c 'expect "\n" {send "pressed enter\n"}
-d:可以输出输出调试信息
示例:expect -d ssh.exp

expect最常用的语法(tcl语言:模式-动作)
单一分支模式语法:
expect "hi" {send "You said hi\n"} 匹配到hi后,会输出"you said hi",并换行,也可以使用\r
多分支模式语法:
expect "hi" { send "You said hi\n" } \ "hehe" { send "Hehe yourself\n" } \ "bye" { send "Good bye\n" }
匹配hi,hello,bye任意字符串时,执行相应输出.等同如下:
expect { "hi" { send "You said hi\n"} "hehe" { send "Hehe yourself\n"} "bye" { send "Good bye\n"} }

五、实例:

1)ssh免交互远程登录

[root@lokott ~]# yum install -y expect已加载插件:fastestmirror, langpacksLoading mirror speeds from cached hostfile...//省略部分[root@lokott shell]# cat a.sh #使用which expect查看其位置#!/usr/bin/expect#设置超时时间    set timeout 20    log_file test.log    log_user 1#变量定义    set hostname [lindex $argv 0]    set passwd [lindex $argv 1]#启动进程,spawn监控    spawn ssh root@$hostname#匹配条件    expect {        "(yes/no)"#exp_continue表示继续向下匹配        {send "yes\r";exp_continue}          "*password"        {send "$passwd\r"}}#转交权限给控制台interact [root@lokott shell]# ./a.sh 192.168.68.129 123456   //第一次登录spawn ssh root@192.168.68.129The authenticity of host '192.168.68.129 (192.168.68.129)' can't be established.ECDSA key fingerprint is SHA256:k/6W9M/dgxVrbMgSx9nIFPGfVgUfLMoIb27ys9ZF+LM.ECDSA key fingerprint is MD5:26:dd:06:b3:32:bd:d6:a3:2f:7c:66:7d:b9:c0:4b:c4.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added '192.168.68.129' (ECDSA) to the list of known hosts.root@192.168.68.129's password: Last login: Wed Dec  4 10:24:33 2019 from 192.168.68.1[root@localhost ~]# exit登出Connection to 192.168.68.129 closed.[root@lokott shell]# ./a.sh 192.168.68.129 123456   //第二次登录上一次登录需要的秘钥已经保存spawn ssh root@192.168.68.129root@192.168.68.129's password: Last login: Wed Dec  4 10:29:42 2019 from 192.168.68.130[root@localhost ~]# exit登出Connection to 192.168.68.129 closed.

上述演示的是直接使用expect脚本实现ssh远程登录的操作过程,而expect脚本也可以被嵌入到普通的脚本文件中,下面给出具体演示:

[root@lokott shell]# cat b.sh #嵌入expect执行实现免交互登录#!/bin/bash#定义普通变量,在该shell脚本中始终有效hostname=$1passwd=$2#嵌入写入expect脚本内容??实现免交互的具体内容/usr/bin/expect<<-EOFspawn ssh root@$hostnameexpect {    "(yes/no)"    {send "yes\r";exp_continue}    "*password"    {send "$passwd\r";}}#下两行是为了返回本地控制台的操作演示expect "*]#"send "exit\r"expect eofEOF#注意EOF的前后都不可以有空格!!![root@lokott shell]# ./b.sh 192.168.68.129 123456spawn ssh root@192.168.68.129root@192.168.68.129's password: Last login: Wed Dec  4 12:22:23 2019 from 192.168.68.130[root@localhost ~]# exit登出Connection to 192.168.68.129 closed.

推荐使用这种方式,因为在实际使用中一般都是在普通脚本中使用expect的,所有嵌入写入比较方便,比较常用!

直接使用expect免交互的完整脚本如下,有兴趣可以试着改为嵌入写入的代码:

[root@lokott shell]# cat ssh.sh #!/usr/bin/expectset timeout 5set hostname [lindex $argv 0]set password [lindex $argv 1]spawn ssh root@$hostnameexpect {"No route to host" exit"Invalid argument" exit"Connection refused" exit"Name or service not known" exit"to continue" {send "yes\r";exp_continue}"password:" {send "$password\r"}}interactexit[root@lokott shell]# ./ssh.sh 192.168.68.133 123456  //服务器非在线spawn ssh root@192.168.68.133ssh: connect to host 192.168.68.133 port 22: No route to host[root@lokott shell]# ./ssh.sh  123456    //参数输入错误spawn ssh root@123456ssh: connect to host 123456 port 22: Invalid argument[root@lokott shell]# ./ssh.sh 192.168.68.129 123456   //正常登录spawn ssh root@192.168.68.129root@192.168.68.129's password: Last login: Wed Dec  4 15:20:51 2019 from 192.168.68.130[root@localhost ~]# 

2)添加用户与用户密码的免交互操作过程

[root@lokott shell]# cat c.sh #!/bin/bashusername=$1password=$2useradd $1[ $? -eq 0 ]&&echo ||exit 1/usr/bin/expect<<-EOFspawn passwd ${username}expect {    "密码:"    {send  "${password}\r";exp_continue}    "密码:"    {send  "${password}\r";}}EOFtail -1 /etc/shadow|awk -F: '{print $1,$2}'userdel -r $1#执行结果如下[root@lokott shell]# ./c.sh zhazhahui 123456spawn passwd zhazhahui更改用户 zhazhahui 的密码 。新的 密码:无效的密码: 密码少于 8 个字符重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。zhazhahui $6$k.MdzCd3$XMUGf5XQV4sE5RJqcwdEoOkd8UVgWtwcguzi6Md5yXcagYvgyE8GmCjzjxkEB5rXR.IRG9j49c36amzkDIe5l1

六、总结

​ 本文主要介绍了expect实现免交互的作用以及结合实际案例讲解其两种使用方式(直接和嵌入)的具体操作过程。

​ 过程主要分为:基本变量定义(timeout最好最先设置)--spawn启动跟踪--expect匹配--interact交付控制权(没有会退出)或者expect eof 结束expect匹配。

​ 务必结合上述的案例自己多使用体会理解!

脚本 密码 过程 控制 登录 语言 输出 输入 命令 字符 用户 语法 进程 普通 信息 变量 字符串 控制台 方式 时间 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 我国网络安全工作的轮廓是 这么看服务器地址 现代化软件开发模型设计 数据库 统计图表 串口服务器通信连接 金华比起奇网络技术 泰山杯网络安全大赛团体得分 福建地区棋牌软件开发 千万别学软件开发有前途吗 移动互联网应用软件开发标语 国网网络安全责任书 临沂舜海网络技术有限公司 东阿软件开发者 我国网络安全产业的规模增长迅速 实用的计算机网络技术课程 数据库能查询公司股权结构吗 网络安全工作汇报季度报 成都市品软件开发工作室 广安市网络安全宣传周 网络安全等级保护法律规定 rust 桌面软件开发框架 海康存储磁盘阵列服务器功率 柯美数字印刷机 服务器 我的世界服务器清理掉落 数据库建立索引会变快吗 国家网络安全产业园经开区 4G网络安全插画 发票上安全接入服务器地址 网络技术pool 深圳创载网络科技是软件开发吗
0