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 expect

Loaded 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 expect

Loaded 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 ~]# expect 

expect1.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 ~]# expect       

expect1.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

回到顶部