linux非交互式自动应答语言——expect

expect是什么

Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。
Expect是一个用来实现自动交互功能的软件套件(Expect [is a] software suite for automating interactive tools)。
Expect语言是基于Tcl的

expect的安装

expect它是一个程序,所以它也是需要提前安装才可以使用的

[root@sjserver ~]# yum -y install expect
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
base                                                                                                   | 3.6 kB  00:00:00     
epel                                                                                                   | 4.7 kB  00:00:00     
extras                                                                                                 | 2.9 kB  00:00:00     
updates                                                                                                | 2.9 kB  00:00:00     
(1/2): epel/x86_64/updateinfo                                                                          | 788 kB  00:00:00     
(2/2): epel/x86_64/primary_db                                                                          | 6.1 MB  00:00:01     
正在解决依赖关系
--> 正在检查事务
---> 软件包 expect.x86_64.0.5.45-14.el7_1 将被 安装

用expect编写脚本

例1:ssh无交互登录到远程服务器

[root@sjserver ~]# vim expect.sh 

#!/usr/bin/expect   //这里需要用expect自己的解释器,注意不要写成bash否则无法识别

spawn ssh [email protected]   //开启一个程序,这个程序是ssh远程登录


expect {               //捕获内容,当出现password的时候,就会向程序发送密码,默认是不换行的,所以需要\r回车换行,多个条件需要花括号括起来
        "password:"
        { send "123456\r"; }
}

interact   //交互,否则会直接退出远程服务器

[root@sjserver ~]# chmod +x expect.sh  //需要加执行权限
[root@sjserver ~]# ./expect.sh 
spawn ssh [email protected]
[email protected]'s password: 
Last login: Mon Jul 27 23:31:00 2020 from 192.168.100.120
[root@server ~]# 

定义和引用变量
用set关键字定义变量,变量名和变量的值中间用空格分开,其他用法与shell脚本一致

[root@sjserver ~]# vim expect.sh 

#!/usr/bin/expect

set ip 192.168.100.100
set username root
set password 123456

spawn ssh $username@$ip


expect {
        "password:"
        { send "$password\r"; }
}

interact

给expect脚本添加一些其他参数,如超时时间,日志等

#!/usr/bin/expect
#超时时间
set timeout 20
#开启日志文件
log_file test.log
#显示信息
log_user 1

set ip 192.168.100.100
set username root
set password 123456

spawn ssh $username@$ip


expect {
        "password:"
        { send "$password\r"; }
}

interact

查看指定的日志文件

[root@sjserver ~]# vim test.log 

spawn ssh [email protected]
[email protected]'s password:
Last login: Tue Jul 28 00:25:00 2020 from 192.168.100.120^M
^[]0;root@server:~^G^[[?1034h[root@server ~]#
^[]0;root@server:~^G[root@server ~]#
^[]0;root@server:~^G[root@server ~]# exit
登出
Connection to 192.168.100.100 closed.^M

远程登录服务器之后可以进行一些操作然后退出都可以免交互

[root@sjserver ~]# vim expect.sh 

#!/usr/bin/expect

set ip 192.168.100.100
set username root
set password 123456

spawn ssh $username@$ip


expect {
        "password:"
        { send "$password\r"; }
}

expect "#"   //当捕获到#号时
send "ls\r"  //查看一下当前目录
send "exit\r"  //退出登录

expect eof   //不需要进行交互了,意味着结束expect程序

运行结果:

[root@sjserver ~]# ./expect.sh 
spawn ssh root@192.168.100.100
root@192.168.100.100's password: 
Last login: Tue Jul 28 00:26:13 2020 from 192.168.100.120
[root@server ~]# ls
123123           a.out        for2.sh      initial-setup-ks.cfg  oushu.sh              ssh.sh    :wq         图片
123123.pub       dead.letter  for3.sh      jindu.sh              paixu1.sh             test.log  zhengze.sh  文档
1.sh             expect1.sh   for4.sh      jishuhe.sh            paixu2.sh             unset.sh  公共        下载
1.txt            expect.sh    for.sh       max.sh                root@192.168.100.200  user.sh   模板        音乐
anaconda-ks.cfg  for1.sh      ifcfg-ens33  ntpdate.sh            shanchu.sh            while.sh  视频        桌面
[root@server ~]# exit
登出
Connection to 192.168.100.100 closed.

引用位置变量传参给expect脚本

[root@sjserver ~]# vim expect.sh 

#!/usr/bin/expect

set username root

set hostname [lindex $argv 0]  //这里定义了第一个位置变量为hostname就是ip地址
set password [lindex $argv 1]  //这里定义了第二个位置变量为密码

spawn ssh $username@$hostname


expect {
        "password:"
        { send "$password\r"; }
}

interact

[root@sjserver ~]# ./expect.sh 192.168.100.100 123456
spawn ssh [email protected]
[email protected]'s password: 
Last login: Tue Jul 28 00:31:08 2020 from 192.168.100.120
[root@server ~]# 

在shell脚本里引用expect程序,无交互的创建一个用户并为其设置密码

[root@server ~]# vim user.sh 

#!/bin/bash
username=$1

useradd $username

/usr/bin/expect <<-EOF

spawn passwd $username
expect {
"密码"     //注意:获取的内容和发送的内容不能在同一行否则执行不成功
{send "123456\r";exp_continue}
"新的密码"
{send "123456\r";}
}
EOF

[root@server ~]# . user.sh wangwu
spawn passwd wangwu
更改用户 wangwu 的密码 。
新的 密码:
无效的密码: 密码少于 8 个字符
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新。

例2:在shell中调用expect程序,ssh远程到服务器上

[root@server ~]# vim expect1.sh

#!/bin/bash

expect -c "
spawn ssh [email protected]
expect \"*password:*\" { send \"123456\r\"}

interact
"

[root@server ~]# ./expect1.sh 
spawn ssh [email protected]
[email protected]'s password: 
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Wed Jul 29 09:45:43 2020 from 192.168.100.100
[root@dnsserver ~]# 

注意:如果要停留在远程服务器上进行交互操作的话,需要在shell脚本里使用expect -c来调用expect程序,然后再使用interact命令,如果用EOF的话使用interact无效,始终只能无交互

名词解释

send:向进程中发送字符串

expect:从进程中读取字符串,例如可以读取用户登录的密码等

spawn:此命令可以启动新的进程操作

interact:表示允许用户进行交互操作,一直保持会话连接

exp_continue:脚本继续向下执行指令,如果这个结果不匹配就再继续查看下一个指定是否匹配

猜你喜欢

转载自blog.csdn.net/shengjie87/article/details/107623916