1.什么是expect
expect是Unix系统中用来进行自动化控制和测试的软件工具,由Don Libes制作,作为Tcl脚本语言的一个扩展,应用在交互式软件中如telnet,ftp,passwd,fsck,rlogin,tip,ssh等等。该工具利用Unix伪终端包装其子进程,允许任意程序通过终端接入进行自动化控制;也可利用Tk工具,将交互程序包装在X11的图形用户界面中。 --维基百科
expect由Don Libes基于Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借助 expect 处理交互的命令,可以将交互过程如:ssh登录,ftp登录,计划性任务,写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,提高系统管理人员的工作效率。
2.expect介绍[root@CentOS-8 data]# expect -usage: expect [-dDhinNv] [-c cmds] [[-[f|b]] cmdfile] [args] Flags are as follows:
-b prefaces a file from which to read commands from
(expect reads one line at a timei from the file)
-c prefaces a command to be executed before any in the script,
may be used multiple times
-d enables diagnostic output
-D enables interactive debugger
-f prefaces a file from which to read commands from
(expect reads the whole file at once)
-h prints this usage message and exits
-i interactively prompts for commands
-n expect doesn't read personal rc file
-N expect doesn't read system-wide rc file
-v prints version and exits
expect 相关命令
spawn 启动新的进程
expect 从进程接收字符串
send 用于向进程发送字符串
interact 允许用户交互
exp_continue 匹配多个字符串在执行动作后加此命令
3. expect 使用
3.1 expect 简单语法
单一分支模式语法:
expect "hi" {send “You said hi\r"} #匹配到hi后,会输出“you said hi”,并换行
多分支模式语法:
expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
3.2.ssh 脚本自动化登录
1.1 ssh_auto
1 #!/usr/bin/expect 2 spawn ssh 192.168.56.25 #进程 3 expect { 4 "yes/no" {send "yes\r";exp_continue} #输入yes 5 "password" {send "123456\r";} #输入密码 6 } 7 expect eof
运行结果如下:
1 [root@CentOS-8 data]# expect ssh_auto 2 spawn ssh 192.168.56.25 3 The authenticity of host '192.168.56.25 (192.168.56.25)' can't be established. 4 RSA key fingerprint is SHA256:4AeVnKTLZZgRG1j4uDeLUlG8TItb44VrcwUQW8SYsKU. 5 Are you sure you want to continue connecting (yes/no)? yes 6 ^C[root@CentOS-8 data]# vim ssh_auto 7 [root@CentOS-8 data]# expect ssh_auto 8 spawn ssh 192.168.56.25 9 The authenticity of host '192.168.56.25 (192.168.56.25)' can't be established. 10 RSA key fingerprint is SHA256:4AeVnKTLZZgRG1j4uDeLUlG8TItb44VrcwUQW8SYsKU. 11 Are you sure you want to continue connecting (yes/no)? yes 12 Warning: Permanently added '192.168.56.25' (RSA) to the list of known hosts. 13 root@192.168.56.25's password: 14 Last login: Thu Oct 31 17:59:05 2019 from 192.168.56.99
3.2 自动登录然后拷取文件
copy_auto
1 #!/usr/bin/expect 2 spawn ssh 192.168.56.25 3 expect { 4 "yes/no" {send "yes\r"} 5 "password" {send "123456\r"} 6 } 7 expect "@CentOS-6" {send "scp /etc/fstab [email protected]:/tmp\r"} 8 expect "yes/no" {send "yes\r"} #发送命令 9 expect "password" {send "123456\r"} 10 expect eof
运行结果:
1 [root@CentOS-8 data]# expect auto_copy_null 2 spawn ssh 192.168.56.25 3 root@192.168.56.25's password: 4 Last login: Thu Oct 31 19:54:28 2019 from 192.168.56.99 5 [root@CentOS-6 ~]$scp /etc/fstab root@192.168.56.99:/tmp 6 root@192.168.56.99's password: 7 fstab 100% 993 1.0KB/s 00:00 8 [root@CentOS-6 ~]$
3.3 interact
interact交互式,你登录了远程,想在此执行任务,保持会话连接.可以加上此命令
在expect eof 之前便可
3.4 expect 变量,参数
expect 是可以自己定义参数的如:
set ip 192.168.56.99
set user root
set passwd 123456
引用参数加上$,$ip,$user,$passwd
expect 位置的参数
位置参数很好,expect也支持位置参数,
set user [Index $agrv 0]
set passwd [Index $agrv 1]
set time [Index $agrv 2]
3.5 shell脚本调用expect 创建用户
shell_expect.sh
1 #!/bin/bash 2 IP=$1 3 LOGPASSWD=$2 4 USER=$3 5 PASSWD=$4 6 expect<<EOF 7 spawn ssh $IP 8 expect { 9 "yes/no" { send "yes\r";exp_continue } 10 "password" { send "$LOGPASSWD\r";exp_continue } 11 } 12 expect "CentOS-6" { send "useradd $USER\r" } 13 expect "CentOS-6" { send "echo $PASSWD | passwd --stdin $USER\r"} 14 expect "CentOS-6" { send "exit\r" } 15 expect eof 16 EOF
执行如下:
1 [root@CentOS-8 data]# bash shell_expect.sh 192.168.56.25 123456 linwong 9090 2 spawn ssh 192.168.56.25 3 root@192.168.56.25's password: 4 Last login: Thu Oct 31 19:55:02 2019 from 192.168.56.99 5 [root@CentOS-6 ~]$useradd linwong 6 [root@CentOS-6 ~]$echo 9090 | passwd --stdin linwong 7 exit 8 Changing password for user linwong. 9 passwd: all authentication tokens updated successfully. 10 [root@CentOS-6 ~]$exit 11 logout 12 Connection to 192.168.56.25 closed. 13 [root@CentOS-8 data]#
4.总结:
expect 是使用ctl语言开发。我尝试着搜索过,不过个资料很少,也没有深入了解,不过expect是非常好的工具。
expect有自己的语法格式,变量定义等。记得expect { expression } expect 与花括号之间记得空格啊,不然语法错误,真是个坑啊
还有send 发送的指令需要双引号,语法错。都是一个个坑,趟过来的。