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 发送的指令需要双引号,语法错。都是一个个坑,趟过来的。

 
01-09 16:46