在上一篇文章中,我们谈到了编写实用的 shell 脚本,我们看到了编写 shell 脚本是多么容易。今天我们将讨论一个对我们的 shell 脚本有魔力的工具;该工具是Expect 命令或Expect 脚本语言,结合详细的expect命令用法示例,希望可以让你更好地了解并使用它。
如何使用expect命令?Expect 命令或expect 脚本语言是一种与需要用户交互的交互式程序或脚本对话的语言。
Expect 脚本语言通过期待输入来工作,然后 Expect 脚本将在没有任何用户交互的情况下发送响应。
你可以说这个工具就是你的机器人,它会自动化你的脚本,那么如何自动化shell脚本呢?下面我们来逐渐学习。
如果你的系统上没有安装 expect 命令,你可以使用以下命令安装它:
$ apt-get install expect
或者在 CentOS 等基于 Red Hat 的系统上:
$ yum install expect
- expect命令
- 使用autoexpect
- 使用变量
- 条件测试
- if-else条件
- While 循环
- For 循环
- 用户定义函数
- interact命令
expect命令
在讲expect命令之前,我们先来看看一些用于交互的Expect命令:
spawn | 启动脚本或程序。 |
expect | 等待程序输出。 |
send | 向你的程序发送回复。 |
interact | 允许你与你的程序进行交互。 |
- spawn 命令启动脚本或程序,如 shell、FTP、Telnet、SSH、SCP 等。
- send 命令向脚本或程序发送回复。
- Expect 命令等待输入。
- interact命令允许你定义预定义的用户交互。
我们将输入一个询问一些问题的 shell 脚本,我们将制作一个可以回答这些问题的 Expect 脚本。
首先,shell 脚本如下所示:
#!/bin/bash
echo "Hello, who are you?"
read $REPLY
echo "Can I ask you some questions?"
read $REPLY
echo "What is your favorite topic?"
read $REPLY
现在我们将编写将自动回答这个问题的 Expect 脚本,expect命令用法示例如下:
#!/usr/bin/expect -f
set timeout -1
spawn ./questions
expect "Hello, who are you?\r"
send -- "Im Adam\r"
expect "Can I ask you some questions?\r"
send -- "Sure\r"
expect "What is your favorite topic?\r"
send -- "Technology\r"
expect eof
第一行定义了expect命令路径,它是
#!/usr/bin/expect
.
在第二行代码中,我们禁用超时。然后使用 spawn 命令启动我们的脚本。
我们可以使用 spawn 来运行我们想要的任何程序或任何其他交互式脚本。
剩下的几行是与我们的 shell 脚本交互的 Expect 脚本。
最后一行表示交互结束。
现在 Showtime,让我们运行我们的答案机器人并确保它可以执行。
$ chmod +x ./answerbot
$./answerbot
凉爽的!!send 命令回答了所有问题。
如果你收到有关 Expect 命令位置的错误,你可以使用 which 命令获取位置:
$ which expect
如何使用expect命令?我们根本没有与我们的脚本进行交互;Expect 程序为我们完成了这项工作。
你可以将上述方法应用于任何交互式脚本或程序。虽然上面的 Expect 脚本很容易编写,但对于某些人来说,Expect 脚本可能有点棘手,你已经知道了。
如何自动化shell脚本?使用autoexpect
要自动构建expect脚本,你可以使用 autoexpect 命令。
autoexpect 的工作方式类似于 expect 命令,但它为你构建自动化脚本。你将要自动化的脚本作为参数传递给 autoexpect,然后回答问题,autoexpect 将你的答案保存在一个文件中。
$ autoexpect ./questions
autoexpect 生成一个名为 script.exp 的文件,其中包含与我们上面所做的相同的代码,但我们现在将保留一些附加内容。
如果你运行自动生成的文件 script.exp,你将看到与预期相同的答案:
惊人的!!那超级容易。
expect命令自动化shell脚本:许多命令会产生可变的输出,例如 FTP 程序,expect 脚本可能会失败或卡住。为了解决这个问题,你可以对可变数据使用通配符,使你的脚本更加灵活。
使用变量
如何自动化shell脚本?你可以使用 set 命令在 expect 脚本中定义变量,如下expect命令用法示例:
set MYVAR 5
要访问变量,请在它前面加上 $ 像这样 $VAR1
要在 expect 脚本中定义命令行参数,我们使用以下语法:
set MYVAR [lindex $argv 0]
这里我们定义了一个变量 MYVAR,它等于第一个传递的参数。
你可以获取第一个和第二个参数并将它们存储在如下变量中:
set my_name [lindex $argv 0]
set my_favorite [lindex $argv 1]
让我们在脚本中添加变量:
#!/usr/bin/expect -f
set my_name [lindex $argv 0]
set my_favorite [lindex $argv 1]
set timeout -1
spawn ./questions
expect "Hello, who are you?\r"
send -- "Im $my_name\r"
expect "Can I ask you some questions?\r"
send -- "Sure\r"
expect "What is your favorite topic?\r"
send -- "$my_favorite\r"
expect eof
现在尝试使用一些参数运行 Expect 脚本以查看输出:
$ ./answerbot SomeName Programming
惊人的!!现在我们的自动化 Expect 脚本更加动态。
条件测试
你可以使用大括号编写条件测试,如下所示:
expect {
"something" { send -- "send this\r" }
"*another" { send -- "send another\r" }
}
如何使用expect命令?我们将更改我们的脚本以返回不同的条件,我们将更改我们的 Expect 脚本来处理这些条件。
我们将使用以下脚本模拟不同的expect:
#!/bin/bash
let number=$RANDOM
if [ $number -gt 25000 ]; then
echo "What is your favorite topic?"
else
echo "What is your favorite movie?"
fi
read $REPLY
当你运行脚本时,它每次都会生成一个随机数,并基于该数字;我们设置了一个条件来返回不同的expect。
让我们制作将处理该问题的 Expect 脚本。
#!/usr/bin/expect -f
set timeout -1
spawn ./questions
expect {
"*topic?" { send -- "Programming\r" }
"*movie?" { send -- "Star wars\r" }
}
expect eof
非常清楚。如果脚本命中主题输出,则expect脚本将发送编程,如果脚本命中电影输出,则expect脚本将发送星球大战。是不是很酷?
if-else条件
你可以在 expect 脚本中使用 if/else 子句,如下expect命令用法示例:
#!/usr/bin/expect -f
set NUM 1
if { $NUM < 5 } {
puts "\Smaller than 5\n"
} elseif { $NUM > 5 } {
puts "\Bigger than 5\n"
} else {
puts "\Equals 5\n"
}
注意:左大括号必须在同一行上。
While 循环
expect语言中的 while 循环必须使用大括号来包含这样的表达式:
#!/usr/bin/expect -f
set NUM 0
while { $NUM <= 5 } {
puts "\nNumber is $NUM"
set NUM [ expr $NUM + 1 ]
}
puts ""
For 循环
与任何脚本或编程语言一样,你可以将 for 循环用于重复性任务,必须指定三个字段,如下格式:
#!/usr/bin/expect -f
for {set NUM 0} {$NUM <= 5} {incr NUM} {
puts "\nNUM = $NUM"
}
puts ""
用户定义函数
你可以使用 proc 定义一个函数,如下所示:
proc myfunc { TOTAL } {
set TOTAL [expr $TOTAL + 1]
return "$TOTAL"
}
之后你可以使用它们。
#!/usr/bin/expect -f
proc myfunc { TOTAL } {
set TOTAL [expr $TOTAL + 1]
return "$TOTAL"
}
set NUM 0
while {$NUM <= 5} {
puts "\nNumber $NUM"
set NUM [myfunc $NUM]
}
puts ""
interact命令
expect命令自动化shell脚本:有时你的expect脚本包含一些你不想与使用你的expect脚本的其他用户共享的敏感信息,例如密码或任何其他数据。因此,你希望脚本从你那里获取此密码并正常继续自动化。
interact命令将控制权恢复到键盘。
当你使用interact命令时,expect 将开始从键盘读取。
此 shell 脚本将询问密码,如下所示:
#!/bin/bash
echo "Hello, who are you?"
read $REPLY
echo "What is you password?"
read $REPLY
echo "What is your favorite topic?"
read $REPLY
现在我们将编写将提示输入密码的 Expect 脚本:
#!/usr/bin/expect -f
set timeout -1
spawn ./questions
expect "Hello, who are you?\r"
send -- "Hi Im Adam\r"
expect "*password?\r"
interact ++ return
send "\r"
expect "*topic?\r"
send -- "Technology\r"
expect eof
键入密码后,键入 ++,控件将从键盘返回到脚本。
如何使用expect命令?由于它的简单性和重要性,Expect 语言被移植到许多语言,如 C#、Java、Perl、Python、Ruby 和 Shell,具有几乎相同的概念和语法。
如何自动化shell脚本?你可以在质量保证、网络测量(例如回声响应时间)、自动文件传输、更新和许多其他用途中使用 expect 脚本语言。
根据以上的expect命令用法示例,我希望你现在已经掌握了 expect 命令、autoexpect 命令的一些最重要的方面,以及如何使用它以更智能的方式自动化你的任务。
谢谢阅读。