expect可以实现shell实现不了的用户交互的需求。expect可以将交互写在一个脚本上,完成很多自动化的动作,比如ssh、ftp登陆等,都是需要交互需求的。expect是需要安装的,直接yum -y install expect安装即可。
expect的四个关键命令为:spawn、expect、send、set,其中spawn是调用要执行的命令,expect是等待命令提示信息的出现也即捕捉用户提示信息,send是发送需要交互的信息来替代手工的输入,set则是输入变量值。
一、expect关键语法
1、关键语法
[#!/usr/bin/expect] 这一行告诉操作系统脚本里的代码使用那一个shell来执行。这里的expect其实和linux下的bash、windows下的cmd是一类东西。 注意:这一行需要在脚本的第一行。
spawn 调用要执行的命令
expect 只有spawn执行的命令的执行结果才被expect捕捉到,主要包括标准输入的提示信息、eof和timeout。等待命令提示信息的出现,也就是捕捉用户输入的提示:
send 发送需要交互的值,替代了用户手动输入内容
set 设置变量值
interact 执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
expect eof 这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于if....endif
PS:expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了。
2、常见设置
set timeout -1 设置expect永不超时
set timeout 300 设置expect 300秒超时,如果超过300没有expect内容出现,则退出
PS:为什么要设置超时时间,因为默认时间是10s,则在交互执行的过程中,很可能会断开,导致任务执行没完成就终止。我司的一个从远程ftp上同步文件的计划任务总是执行终止,后来设置了超时时间为-1就可以了。
二、expect的用法示例
1、一个简单的拉取文件的例子
#!/usr/bin/expect -f
set passwd "123456" ##这个是你设置的密码
set timeout -1 ##设置超时时间
spawn sftp -P 2022 [email protected]
expect "password:"
send "$passwd\r"
expect "sftp>"
send "get -r data/201711*\r"
expect "sftp>"
send "exit\r"
interact
2、一个小例子,用于linux下账户的建立:
1 #!/usr/bin/expect
2
3 set passwd "mypasswd"
4 set timeout 60
5
6 if {$argc != 1} {
7 send "usage ./account.sh \$newaccount\n"
8 exit
9 }
10
11 set user [lindex $argv [expr $argc-1]]
12
13 spawn sudo useradd -s /bin/bash -g mygroup -m $user
14
15 expect {
16 "assword" {
17 send_user "sudo now\n"
18 send "$passwd\n"
19 exp_continue
20 }
21 eof
22 {
23 send_user "eof\n"
24 }
25 }
26
27 spawn sudo passwd $user
28 expect {
29 "assword" {
30 send "$passwd\n"
31 exp_continue
32 }
33 eof
34 {
35 send_user "eof"
36 }
37 }
38
39 spawn sudo smbpasswd -a $user
40 expect {
41 "assword" {
42 send "$passwd\n"
43 exp_continue
44 }
45 eof
46 {
47 send_user "eof"
48 }
49 }
以上脚本的注意点如下:
3、下面这个例子比较特殊,在整个过程中就不能expect eof了
1 #!/usr/bin/expect
2 set mypassword=123456
3 set timeout 30
4 spawn ssh 10.192.224.224
5 expect "password:"
6 send "mypassword\n"
7 expect "*$"
8 send "mkdir tmpdir\n"
9 expect "*$"
这个例子实际上是通过ssh去登录远程机器,并且在远程机器上创佳一个目录,我们看到在我们输入密码后并没有去expect eof,这是因为ssh这个spawn并没有结束,而且手动操作时ssh实际上也不会自己结束除非你exit;所以你只能expect bash的提示符,当然也可以是机器名等,这样才可以在远程创建一个目录。注意,请不要用spawn mkdir tmpdir,这样会使得上一个spawn即ssh结束,那么你的tmpdir将在本机建立。当然实际情况下可能会要你确认ssh key,可以通过并行的expect进行处理,不多赘述。
PS:在shell脚本中插入expect命令,格式为如下
#!/bin/sh
expect <"
send "mkdir xxxxx\r"
send "exit\r"
expect eof
! ##结尾