shell脚本编程之expect
一.expect概述
1.expect介绍
expect 是由Don Libes基于Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借助Expect处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率。
2.expect命令
expect 语法:expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
常用选项
-c:从命令行执行expect脚本,默认expect是交互地执行的
示例:expect -c "expect "
" {send "pressed enter
"}
-d:可以输出输出调试信息
示例:expect -d ssh.exp
expect中相关命令
spawn:
启动新的进程
send:
用于向进程发送字符串
expect:
从进程接收字符串
interact:
允许用户交互
exp_continue
匹配多个字符串在执行动作后加此命令
3.安装expect软件包
[root@node101.yinzhengjie.org.cn ~]# yum info expectLoaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.huaweicloud.com
* epel: mirrors.aliyun.com
* extras: mirrors.huaweicloud.com
* updates: mirrors.aliyun.com
Available Packages
Name : expect
Arch : x86_64
Version : 5.45
Release : 14.el7_1
Size : 262 k
Repo : base/7/x86_64
Summary : A program-script interaction and testing utility
URL : http://expect.nist.gov/
License : Public Domain
Description : Expect is a tcl application for automating and testing
: interactive applications such as telnet, ftp, passwd, fsck,
: rlogin, tip, etc. Expect makes it easy for a script to
: control another program and interact with it.
:
: This package contains expect and some scripts that use it.
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# yum info expect #查看expect软件包相关信息
[root@node101.yinzhengjie.org.cn ~]# yum -y install expectLoaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
epel/x86_64/metalink | 8.6 kB 00:00:00
* base: mirrors.aliyun.com
* epel: mirrors.aliyun.com
* extras: ap.stykers.moe
* updates: mirrors.aliyun.com
base | 3.6 kB 00:00:00
epel | 5.3 kB 00:00:00
extras | 2.9 kB 00:00:00
updates | 2.9 kB 00:00:00
(1/2): epel/x86_64/updateinfo | 1.0 MB 00:00:06
(2/2): epel/x86_64/primary_db | 6.9 MB 00:00:14
Resolving Dependencies
--> Running transaction check
---> Package expect.x86_64 0:5.45-14.el7_1 will be installed
--> Processing Dependency: libtcl8.5.so()(64bit) for package: expect-5.45-14.el7_1.x86_64
--> Running transaction check
---> Package tcl.x86_64 1:8.5.13-8.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
============================================================================================================================================================================
Package Arch Version Repository Size
============================================================================================================================================================================
Installing:
expect x86_64 5.45-14.el7_1 base 262 k
Installing for dependencies:
tcl x86_64 1:8.5.13-8.el7 base 1.9 M
Transaction Summary
============================================================================================================================================================================
Install 1 Package (+1 Dependent package)
Total download size: 2.1 M
Installed size: 4.9 M
Downloading packages:
(1/2): expect-5.45-14.el7_1.x86_64.rpm | 262 kB 00:00:06
(2/2): tcl-8.5.13-8.el7.x86_64.rpm | 1.9 MB 00:00:07
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 294 kB/s | 2.1 MB 00:00:07
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : 1:tcl-8.5.13-8.el7.x86_64 1/2
Installing : expect-5.45-14.el7_1.x86_64 2/2
Verifying : 1:tcl-8.5.13-8.el7.x86_64 1/2
Verifying : expect-5.45-14.el7_1.x86_64 2/2
Installed:
expect.x86_64 0:5.45-14.el7_1
Dependency Installed:
tcl.x86_64 1:8.5.13-8.el7
Complete!
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# yum -y install expect #安装expect工具
二.expect最常用的语法(tcl语言:模式-动作)
1.expect的单分支语法
[root@node101.yinzhengjie.org.cn ~]# expectexpect1.1> expect "hi" {send "say hi
"} #捕捉用户输入的"hi",然后给用户发送"say hi
"
hi #这一行是我输入的,由于被我上面定义的语句捕捉到了,下面一行的输出信息就是我之前自定义的字符串信息。
say hi
expect1.2> exit #如果不想使用该程序了可以输入"exit"来正常退出交互式界面
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
2.expect的多分支语法
[root@node101.yinzhengjie.org.cn ~]# expectexpect1.1> expect "hi" {send "say hi
"}
+> "bye" {send "byebye
"}
bye
byebye
expect1.2> exit
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# expect #匹配hi,hello,bye任意字符串时,执行相应输出。上面的写法和下面的写法功能是相同的。
expect1.1> expect {
+> "hi" {send "You said hi
"}
+> "hehe" {send "hehe yourself
"}
+> "bye" {send "Good bye
"}
+> }
bye
Good bye
expect1.2>
expect1.2> exit
[root@node101.yinzhengjie.org.cn ~]#
三.expect脚本案例实战
1.spawn(启动新的进程)案例
[root@node101.yinzhengjie.org.cn ~]# ll .ssh/total 16
-rw-------. 1 root root 413 Jul 9 10:27 authorized_keys
-rw-------. 1 root root 1675 Jul 9 10:27 id_rsa
-rw-r--r--. 1 root root 413 Jul 9 10:27 id_rsa.pub
-rw-r--r--. 1 root root 1608 Jul 9 10:28 known_hosts
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# rm -rf .ssh
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ll /etc/issue
-rw-r--r--. 1 root root 23 Nov 23 2018 /etc/issue
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ll backup/
total 0
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/scp_expect.sh
#!/usr/bin/expect #注意,这一行需要写expect命令的执行路径
#
#********************************************************************
#Author: yinzhengjie
#QQ: 1053419035
#Date: 2019-11-29
#FileName: shell/scp_expect.sh
#URL: http://www.cnblogs.com/yinzhengjie
#Description: The test script
#Copyright notice: original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************
spawn scp /etc/issue root@172.30.1.101:/root/backup
expect {
"yes/no" { send "yes
";exp_continue }
"password" { send "yinzhengjie
" }
}
expect eof
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# chmod +x shell/scp_expect.sh #添加执行权限
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ./shell/scp_expect.sh #执行脚本后,我们发现无需像之前那样手动输出"yes"和密码啦~取而代之的是脚本帮咱们干活了。
spawn scp /etc/issue root@172.30.1.101:/root/backup
The authenticity of host "172.30.1.101 (172.30.1.101)" can"t be established.
ECDSA key fingerprint is SHA256:KEchoZnVBkijeoWfG2nvx2ptthsXv7IjkxIJYule57g.
ECDSA key fingerprint is MD5:52:c8:f5:6e:5f:cf:44:ec:c4:11:60:d2:d0:31:3c:da.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added "172.30.1.101" (ECDSA) to the list of known hosts.
root@172.30.1.101"s password:
issue 100% 23 38.2KB/s 00:00
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ll backup
total 4
-rw-r--r-- 1 root root 23 Nov 29 19:21 issue
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/scp_expect.sh
2.interact(允许用户交互)案例
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect1.sh#!/usr/bin/expect
#
#********************************************************************
#Author: yinzhengjie
#QQ: 1053419035
#Date: 2019-11-29
#FileName: shell/scp_expect.sh
#URL: http://www.cnblogs.com/yinzhengjie
#Description: The test script
#Copyright notice: original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************
spawn ssh yinzhengjie@172.30.1.101
expect {
"yes/no" { send "yes
";exp_continue }
"password" { send "yinzhengjie
" }
}
interact
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ./shell/ssh_expect1.sh
spawn ssh yinzhengjie@172.30.1.101
yinzhengjie@172.30.1.101"s password:
Last login: Sat Nov 30 17:05:32 2019 from 172.30.1.101
[yinzhengjie@node101.yinzhengjie.org.cn ~]$
[yinzhengjie@node101.yinzhengjie.org.cn ~]$ who
yinzhengjie pts/1 2019-11-30 17:06 (172.30.1.101)
root pts/3 2019-11-29 08:24 (172.30.1.254)
root pts/2 2019-11-29 08:24 (172.30.1.254)
[yinzhengjie@node101.yinzhengjie.org.cn ~]$
[yinzhengjie@node101.yinzhengjie.org.cn ~]$ exit
logout
Connection to 172.30.1.101 closed.
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect1.sh
3.变量使用案例
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect2.sh#!/usr/bin/expect
#
#********************************************************************
#Author: yinzhengjie
#QQ: 1053419035
#Date: 2019-11-29
#FileName: shell/scp_expect.sh
#URL: http://www.cnblogs.com/yinzhengjie
#Description: The test script
#Copyright notice: original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************
set host 172.30.1.101
set user yinzhengjie
set password yinzhengjie
spawn ssh ${user}@${host}
expect {
"yes/no" { send "yes
";exp_continue }
"password" { send "${password}
" }
}
interact
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ./shell/ssh_expect2.sh
spawn ssh yinzhengjie@172.30.1.101
yinzhengjie@172.30.1.101"s password:
Last login: Sat Nov 30 17:09:58 2019 from 172.30.1.101
[yinzhengjie@node101.yinzhengjie.org.cn ~]$
[yinzhengjie@node101.yinzhengjie.org.cn ~]$ whoami
yinzhengjie
[yinzhengjie@node101.yinzhengjie.org.cn ~]$
[yinzhengjie@node101.yinzhengjie.org.cn ~]$ exit
logout
Connection to 172.30.1.101 closed.
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect2.sh
4.位置参数案例
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect3.sh#!/usr/bin/expect
#
#********************************************************************
#Author: yinzhengjie
#QQ: 1053419035
#Date: 2019-11-29
#FileName: shell/scp_expect.sh
#URL: http://www.cnblogs.com/yinzhengjie
#Description: The test script
#Copyright notice: original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************
set host [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh ${user}@${host}
expect {
"yes/no" { send "yes
";exp_continue }
"password" { send "${password}
" }
}
interact
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ./shell/ssh_expect3.sh 172.30.1.101 yinzhengjie yinzhengjie
spawn ssh yinzhengjie@172.30.1.101
yinzhengjie@172.30.1.101"s password:
Last login: Sat Nov 30 17:10:27 2019 from 172.30.1.101
[yinzhengjie@node101.yinzhengjie.org.cn ~]$
[yinzhengjie@node101.yinzhengjie.org.cn ~]$ whoami
yinzhengjie
[yinzhengjie@node101.yinzhengjie.org.cn ~]$
[yinzhengjie@node101.yinzhengjie.org.cn ~]$ exit
logout
Connection to 172.30.1.101 closed.
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect3.sh
5.登录后执行多个命令案例
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect4.sh#!/usr/bin/expect
#
#********************************************************************
#Author: yinzhengjie
#QQ: 1053419035
#Date: 2019-11-29
#FileName: shell/scp_expect.sh
#URL: http://www.cnblogs.com/yinzhengjie
#Description: The test script
#Copyright notice: original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************
set host [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set createuser [lindex $argv 3]
set createpasswd [lindex $argv 4]
spawn ssh ${user}@${host}
expect {
"yes/no" { send "yes
";exp_continue }
"password" { send "${password}
" }
}
expect "]#" { send "useradd ${createuser}
" }
expect "]#" { send "echo ${createpasswd} |passwd --stdin ${createuser}
" }
expect "]#" { send "who
" }
send "exit
"
expect eof
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# who
root pts/3 2019-11-29 08:24 (172.30.1.254)
root pts/2 2019-11-29 08:24 (172.30.1.254)
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# id jason
id: jason: no such user
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ./shell/ssh_expect4.sh 172.30.1.101 root yinzhengjie jason 123456
spawn ssh root@172.30.1.101
root@172.30.1.101"s password:
Last login: Sat Nov 30 17:23:11 2019 from 172.30.1.101
[root@node101.yinzhengjie.org.cn ~]# useradd jason
[root@node101.yinzhengjie.org.cn ~]# echo 123456 |passwd --stdin jason
Changing password for user jason.
passwd: all authentication tokens updated successfully.
[root@node101.yinzhengjie.org.cn ~]# who
root pts/1 2019-11-30 17:27 (172.30.1.101)
root pts/3 2019-11-29 08:24 (172.30.1.254)
root pts/2 2019-11-29 08:24 (172.30.1.254)
[root@node101.yinzhengjie.org.cn ~]# exit
logout
Connection to 172.30.1.101 closed.
[root@node101.yinzhengjie.org.cn ~]# who
root pts/3 2019-11-29 08:24 (172.30.1.254)
root pts/2 2019-11-29 08:24 (172.30.1.254)
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# id jason
uid=1049(jason) gid=1049(jason) groups=1049(jason)
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect4.sh
6.shell脚本调用expect
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect5.sh#!/bin/bash
#
#********************************************************************
#Author: yinzhengjie
#QQ: 1053419035
#Date: 2019-11-30
#FileName: shell/ssh_expect5.sh
#URL: http://www.cnblogs.com/yinzhengjie
#Description: The test script
#Copyright notice: original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************
ip=$1
user=$2
password=$3
expect <<EOF
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes
";exp_continue }
"password" { send "$password
" }
}
expect "]#" { send "useradd jason2019
" }
expect "]#" { send "echo yinzhengjie |passwd --stdin jason2019
" }
expect "]#" { send "who
" }
expect "]#" { send "exit
" }
expect eof
EOF
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# who
root pts/3 2019-11-29 08:24 (172.30.1.254)
root pts/2 2019-11-29 08:24 (172.30.1.254)
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# id jason2019
id: jason2019: no such user
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# bash shell/ssh_expect5.sh 172.30.1.101 root yinzhengjie
spawn ssh root@172.30.1.101
root@172.30.1.101"s password:
Last login: Sat Nov 30 17:27:57 2019 from 172.30.1.101
[root@node101.yinzhengjie.org.cn ~]# useradd jason2019
[root@node101.yinzhengjie.org.cn ~]# echo yinzhengjie |passwd --stdin jason2019
Changing password for user jason2019.
passwd: all authentication tokens updated successfully.
[root@node101.yinzhengjie.org.cn ~]# who
root pts/1 2019-11-30 17:38 (172.30.1.101)
root pts/3 2019-11-29 08:24 (172.30.1.254)
root pts/2 2019-11-29 08:24 (172.30.1.254)
[root@node101.yinzhengjie.org.cn ~]# exit
logout
Connection to 172.30.1.101 closed.
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# id jason2019
uid=1050(jason2019) gid=1050(jason2019) groups=1050(jason2019)
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# who
root pts/3 2019-11-29 08:24 (172.30.1.254)
root pts/2 2019-11-29 08:24 (172.30.1.254)
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect5.sh
7.模拟给集群批量创建用户的脚本
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect6.sh#!/bin/bash
#
#********************************************************************
#Author: yinzhengjie
#QQ: 1053419035
#Date: 2019-11-30
#FileName: shell/ssh_expect5.sh
#URL: http://www.cnblogs.com/yinzhengjie
#Description: The test script
#Copyright notice: original works, no reprint! Otherwise, legal liability will be investigated.
#********************************************************************
while read ip ;do
user=root
password=yinzhengjie
expect <<EOF
set timeout 30
spawn ssh $user@$ip
expect {
"yes/no" { send "yes
";exp_continue }
"password" { send "$password
" }
}
expect "]#" { send "useradd hadoop
" }
expect "]#" { send "echo yinzhengjie |passwd --stdin hadoop
" }
expect "]#" { send "who
" }
expect "]#" { send "exit
" }
expect eof
EOF
done < /root/shell/iplist.txt
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/iplist.txt #咱们这里定义了需要连接集群的主机IP
172.30.1.101
172.30.1.102
172.30.1.103
172.30.1.104
172.30.1.105
172.30.1.106
172.30.1.107
172.30.1.108
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# bash shell/ssh_expect6.sh #执行脚本后发现会有很多输出信息,由于我试验的时候之开机了172.30.1.101这台虚拟机,其它虚拟机全部关机了,结果脚本只在开机的虚拟机中执行成功啦,其它主机报错提示找不到主机路由。
spawn ssh root@172.30.1.101
root@172.30.1.101"s password:
Last login: Sat Nov 30 17:38:48 2019 from 172.30.1.101
[root@node101.yinzhengjie.org.cn ~]# useradd hadoop
[root@node101.yinzhengjie.org.cn ~]# echo yinzhengjie |passwd --stdin hadoop
Changing password for user hadoop.
passwd: all authentication tokens updated successfully.
[root@node101.yinzhengjie.org.cn ~]# who
root pts/1 2019-11-30 17:53 (172.30.1.101)
root pts/3 2019-11-29 08:24 (172.30.1.254)
root pts/2 2019-11-29 08:24 (172.30.1.254)
[root@node101.yinzhengjie.org.cn ~]# exit
logout
Connection to 172.30.1.101 closed.
spawn ssh root@172.30.1.102
ssh: connect to host 172.30.1.102 port 22: No route to host
expect: spawn id exp6 not open
while executing
"expect "]#" { send "useradd hadoop
" }"
spawn ssh root@172.30.1.103
ssh: connect to host 172.30.1.103 port 22: No route to host
expect: spawn id exp6 not open
while executing
"expect "]#" { send "useradd hadoop
" }"
spawn ssh root@172.30.1.104
ssh: connect to host 172.30.1.104 port 22: No route to host
expect: spawn id exp6 not open
while executing
"expect "]#" { send "useradd hadoop
" }"
spawn ssh root@172.30.1.105
ssh: connect to host 172.30.1.105 port 22: No route to host
expect: spawn id exp6 not open
while executing
"expect "]#" { send "useradd hadoop
" }"
spawn ssh root@172.30.1.106
ssh: connect to host 172.30.1.106 port 22: No route to host
expect: spawn id exp6 not open
while executing
"expect "]#" { send "useradd hadoop
" }"
spawn ssh root@172.30.1.107
ssh: connect to host 172.30.1.107 port 22: No route to host
expect: spawn id exp6 not open
while executing
"expect "]#" { send "useradd hadoop
" }"
spawn ssh root@172.30.1.108
ssh: connect to host 172.30.1.108 port 22: No route to host
expect: spawn id exp6 not open
while executing
"expect "]#" { send "useradd hadoop
" }"
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# id hadoop #很显然,只有172.30.1.101主机命令执行成功了。
uid=1051(hadoop) gid=1051(hadoop) groups=1051(hadoop)
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# cat shell/ssh_expect6.sh
以上是 shell脚本编程之expect 的全部内容, 来源链接: utcz.com/z/515752.html