Linux技巧(五):expect安装与介绍 | 精美案例 | bash: spawn: command not found详解

悠悠 2023-10-02 10:41 9阅读 0赞

前言

在运行expect脚本时,一步小心,就有可能导致如下错误!

案例运行结果+答案:

[root@RHEL7 expect]# . ssh.exp
bash: spawn: command not found…
couldn’t read file “{“: no such file or directory
bash: yes/no: No such file or directory

问题根源:

在执行脚本时,用的是#. file.exp(错误运行方法) 而不是 #./file.exp(正确运行方法)。

问题就出在这个斜杠上。

shell运行的5种方式

第一种使用绝对路径执行

第二种使用相对路径执行,如./的方式

第三种使用 sh命令来执行 格式 sh 脚本名 不需要执行权限 -x参数(显示执行过程)

第四种使用 . (空格)脚本名称的方式执行 不需要执行权限 . a.sh

第五种使用 source 脚本名称 不需要执行权限(主要用于生效配置文件)

案例中的expect用第四种方法 . (空格)来执行就会报错:

  1. [root@RHEL7 expect]# . ssh.exp
  2. bash: spawn: command not found...
  3. couldn't read file "{": no such file or directory
  4. bash: yes/no: No such file or directory

第二种,相对路径的方式执行就可以了(需要提前对脚本文件chmod +x 添加执行权限)。

注:普通的bash shell,以上5种执行方法均可,expect就没这么好使了,优先选第二种方式!


¥¥¥¥¥ 特别说明:**上面的使用expect时发生的错误,由此引出下文**¥¥¥¥¥


一、expect介绍

1.1、expect 介绍

expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。

expect自动交互流程:

spawn启动指定进程—-expect获取指定关键字—-send向指定程序发送指定字符—-执行完成退出.

2.2、expect常用命令

spawn 交互程序开始后面跟命令或者指定程序
expect 等待一个进程的反馈,获取匹配信息匹配成功则执行expect后面的程序动作
send exp_send 用于发送指定的字符串信息
exp_continue 在expect中多次匹配就需要用到
send_user 用来打印输出 相当于shell中的echo
exit 退出expect脚本
eof expect执行结束 退出
set 定义变量
puts 输出变量
set timeout 设置超时时间
interact    退出自动化,开始允许用户交互

二、expect安装

2.1、安装expect依赖tcl

1)下载依赖包

http://www.tcl.tk/software/tcltk/downloadnow84.tml

选择: tcl8.4.20-src.tar.gz

watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA6KGA54We6ZW_6Jm5_size_19_color_FFFFFF_t_70_g_se_x_16

2)安装依赖

  1. #tar zxf tcl8.4.20-src.tar.gz -C /usr/src/
  2. #cd /usr/src/tcl8.4.20
  3. #ls 可以看到解压后,该工具支持多种系统
  4. #cd unix/ 进入unix系统
  5. #./configure --prefix=/usr/local/tcl --enable-shared 开启共享功能
  6. #make -j 4
  7. #make install

watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA6KGA54We6ZW_6Jm5_size_20_color_FFFFFF_t_70_g_se_x_16

3)复制tcl的配置文件到上一级目录文件夹中(配置)

  1. #cd /usr/src/tcl8.4.20/unix/ 注:tcl 本身是支持windows和mac的,需切换一下目录
  2. #ls
  3. #cp tclUnixPort.h ../generic/ 把配置文件复制一份到上级目录的文件夹下(安装expect时要用到)

watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA6KGA54We6ZW_6Jm5_size_20_color_FFFFFF_t_70_g_se_x_16 1

2.2、安装expect

1)下载安装包

下载地址:
expect5.45.tar.gz
https://sourceforge.net/projects/expect/files/latest/download

watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA6KGA54We6ZW_6Jm5_size_20_color_FFFFFF_t_70_g_se_x_16 2

  1. #cd
  2. #cd mypackage 切换到压缩包存放位置

watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA6KGA54We6ZW_6Jm5_size_17_color_FFFFFF_t_70_g_se_x_16

2)安装expect

  1. #tar zxf expect5.45.tar.gz -C /usr/src 解压到指定位置
  2. #cd /usr/src/expect5.45/ 切换到解压目录
  3. #./configure --prefix=/usr/local/expect --with-tcl=/usr/local/tcl/lib --with-tclinclude=/usr/src/tcl8.4.20/generic/
  4. #make -j 4
  5. #make install

注:prefix指定安装路径 ;with 添加对tcl支持 指定tcl lib库的地址 ;引用一下tcl的配置文件,使两者关联起来。

3)给expect创建软链接(便于记忆和使用)

  1. #ln -s /usr/local/tcl/bin/expect /usr/local/expect/bin/expect
  2. #ln -s /usr/local/tcl/bin/expect /bin/expect 同时也可以连接到bin下面和/bin/bash同级目录
  3. #ln -s /usr/local/tcl/bin/expect /usr/bin/expect 做软链接(便于使用)

注:expect的命令实际是在Tcl包里,并不是在expect包里。
所以需要把tcl中的expect命令做一个软链接,链接到expect包里。

附:以上是手动安装,当然也可以用yum安装,yum可以自动解决依赖问题。
#yum -y install expect

三、问题还原与处理

3.1、编写脚本(报错案例)

#vim ssh.exp

  1. #!/usr/bin/expect -f #注:这里的-f不是必须
  2. set timeout 30
  3. spawn ssh root@127.0.0.1
  4. expect { #注:关键字与大括号之间有个空格
  5. "yes/no" {send "yes\r" ; exp_continue }
  6. "password:" {send "root\r" }
  7. }
  8. interact

案例中,每行代码详解

1. [#!/usr/bin/expect]
这一行告诉操作系统脚本里的代码使用哪一个shell来执行。这里的expect其实和linux下的bash、windows下的cmd是一类东西。
注意:这一行需要在脚本的第一行。

2. [set timeout 30]

设置超时时间的,现在你只要记住他的计时单位是:秒

注:如果设置为-1,不予超时

3. [spawn ssh root@**127.0.0.1]**
spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。所以不要用 “which spawn“之类的命令去找spawn命令。 它主要的功能是给ssh运行进程加个壳,用来传递交互指令。

4. [expect “password:”]

expect {

“yes/no” { send “yes\r” ;exp_continue}

“password:” { send “123456\r”}

}

这里的expect也是expect的一个内部命令,expect的shell命令和内部命令是一样的,但不是一个功能,习惯就好了。

这个命令的意思是判断上次输出结果里是否包含“yes/no”的字符串,如果有则立即通过send返回一个值,继续判断是否带有password字符串 有则通过send返回一个值 ,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒

5. [send “root\r”]
这里就是执行交互动作,与手工输入密码的动作等效。
温馨提示: 命令字符串结尾别忘记加上 “\r”,如果出现异常等待的状态可以核查一下。

6. [interact]
执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。

3.2、问题处理

#**chmod +x ssh.exp 给脚本添加执行权限(不赋x执行权限,./ 无法看到脚本,也就难以运行了
#
. ssh.exp** 注:点后面有空格。这种写法是shell的第四种执行方法(执行expect就是错误方法)

  1. [root@RHEL7 expect]# . ssh.exp
  2. bash: spawn: command not found...
  3. couldn't read file "{": no such file or directory
  4. bash: yes/no: No such file or directory

就是这个错误,各种找度娘,问题没能找到合适的答案,这是一个细节问题。
expect的执行和bash shell的执行,无论是语法还是执行方式,都有着差异。
运行expect时,需要采用第二种,采用当前路径#./的方式执行(需提前给脚本赋予x执行权限)

watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBA6KGA54We6ZW_6Jm5_size_18_color_FFFFFF_t_70_g_se_x_16

四、expect精美案例

1.写一个简略版的远程登录

#vim 1.exp

  1. #!/usr/bin/expect
  2. spawn ssh saneri@192.168.56.103 df -Th
  3. expect "*password"
  4. send "123456\n"
  5. expect eof

2.写一个expect脚本,执行多条命令

#vim 2.exp

  1. #!/usr/bin/expect -f
  2. set timeout 10
  3. spawn sudo su - root
  4. expect "*password*"
  5. send "123456\r"
  6. expect "#*"
  7. send "ls\r"
  8. expect "#*"
  9. send "df -Th\r"
  10. send "exit\r"
  11. expect eof

3.内部自定义参数的远程登录

#vim 3.exp

  1. #!/usr/tcl/bin/expect
  2. set timeout 30
  3. set host "101.200.241.109"
  4. set username "root"
  5. set password "123456"
  6. spawn ssh $username@$host
  7. expect "*password*" {send "$password\r"}
  8. interact

4.expect外部参数个数和外部参数的取用

#vim 4.exp

  1. #!/usr/tcl/bin/expect
  2. if {$argc < 3} {
  3. puts "Usage:cmd <host> <username> <password>"
  4. exit 1
  5. }
  6. set timeout -1
  7. set host [lindex $argv 0]
  8. set username [lindex $argv 1]
  9. set password [lindex $argv 2]
  10. spawn ssh $username@$host
  11. expect "*password*" {send "$password\r"}
  12. interact

在expect中,$argc表示参数个数,而参数值存放在$argv中,

比如取第一个参数就是[lindex $argv 0],以此类推。

尾言

版本在迭代,学习的脚步不能停,一旦停下,储备知识可能就过时了,要做到时时新事事新,及时更新自己的技术储备,加油少年!

如果你觉得还不错,赶快点赞收藏吧!

发表评论

表情:
评论列表 (有 0 条评论,9人围观)

还没有评论,来说两句吧...

相关阅读