目录
5.1 Here Document 免交互
5.1.1 Here Document 概述
5.1.2 Here Document 免交互
1. 通过read命令接收输入并打印
5.1.3 Here Document变量设定
5.1.4 Here Document 格式控制
(1)关闭变量替换的功能。
(2)去掉每行之前的TAB字符。
5.1.5 Here Document 多行注释
5.2expect免交互
5.2.1 expect概述
5.2.2 except 安装
(1)挂载光盘
(2)制作本地 YUM源
(3)执行安装命令
5.2.3 基本命令介绍
(1)脚本解释器
(2) expect/send
(3) spawn
(4)结束符
(5) set
(6) exp_continue
(7) send_user
(8)接收参数
5.2.4 expect 语法
1. 语法结构
(1)单一分支语法
(2)多分支模式语法
2.expect 执行方式
(1)直接执行
(2)嵌入执行
5.1 Here Document 免交互
5.1.1 Here Document 概述
Here Document是一个特殊用途的代码块。它在Linux Shell中使用I/O重定向的方式将命令列表提供给交互式程序或命令,比如ftp、cat或read命令。Here Document是标准输入的一种替代品,可以帮助脚本开发人员不必使用临时文件来构建输入信息,而是直接就地生产出一个文件并用作命令的标准输入。它的基本语法格式如下。
特殊字符“ << "在标记和命令之前,这样做的目的是将命令块的输出重定向到程序或命令的stdin。标记的选择要确保不会出现在其他地方,避免出现混淆;两个标记之间的内容被当做是一个文件并用作“命令”的标准输入。另外Here Document也可以与非交互式程序和命令一起使用。在实际使用过程中,有四点需要注意。
> 标记可以使用任意的合法字符;
> 结尾的标记一定要顶格写,前面不能有任何字符;
> 结尾的标记后面也不能有任何字符(包括空格);
> 开头的标记前后的空格会被省略掉。
在Linux系统中使用wc-|命令后面直接跟文件名就可以统计文件内有多少行内容。采用HereDocument免交互方式也可以实现对行数的统计。将要统计的内容置于标记“EOF”之间,直接将内容传给wc-I来统计,具体操作如下所示。
5.1.2 Here Document 免交互
在编写Shell脚本时使用 Here Document可以实现免交互,通过 Here Document可以将一些简单的交互任务的交互过程去除掉,尤其是在编写脚本的过程中。具体示例如下所示。
1. 通过read命令接收输入并打印
通常使用read命令接收用户的输入值时会有交互过程,尤其是在脚本执行过程中遇到read命令,脚本会停下来等待用户输入值后才会继续。本示例中的输入值是两个EOF标记之间的部分,也就是“Hi”,这将作为变量i的值。在最后echo打印变量i的值,其值为“Hi”。2. 通过passwd给用户设置密码
通过passwd命令给jerry用户设置密码,为避免重复交互,可使用Here Document的方式。EOF标记之间的两行是输入的密码和确认密码,两行内容必须保持一致,否则密码设置不成功。此脚本执行后不会输出任何信息,可另开一个终端使用jerry用户登录,输入新修改的密码来验证密码是否修改正确。
5.1.3 Here Document变量设定
Here Document也支持使用变量,如果标记之间有变量被使用,会先替换变量值。如果想要将一些内容写入文件,除了常规的方法外,也可以使用Here Document。如果写入的内容中包含变量,在写入文件时要先将变量替换成实际值,在结合cat命令完成写入。
5.1.4 Here Document 格式控制
Here Document 支持两种控制输出格式的类型:关闭变量替换的功能与去掉每行之前
的TAB字符。下面通过示例的方式分别介绍其使用具体方法。
(1)关闭变量替换的功能。
关闭变量替换的功能,就是希望按照字符原本的样子输出,不做任何修改或替换。
(2)去掉每行之前的TAB字符。
本示例的标记内,每行都有一个TAB字符。在第一行的标记前面加‘-’,这个表示要抑制各行首TAB的作用。
5.1.5 Here Document 多行注释
Bash的默认注释是“#”,该注释方法只支持单行注释,在Shell脚本的工作中,“#”右侧的任何字符串,bash都会将其忽略。Here Document的引入解决了多行注释的问题,其语法格式如下。
: << DO-NOTHING
第一行注释
第二行注释
DO-NOTHING
上述语法结构中“:”代表什么都不做的空命令。中间标记区域的内容不会被执行,会被bash忽略掉,因此可达到批量注释的效果。下面脚本用于演示Shell中多行注释,“:”开头的Here Document标记内容不会被执行,在需要使用多行注释的时候可以采用此方法。
[root@localhost ~]# vim here multi.sh#!/bin/bash
:<<BASH-HERE
11多行注释
the first comment.
the second comment.
test line.
BASH-HERE
echo "exec string."
[root@localhost ~]# sh here multi.sh
exec string.
5.2expect免交互
5.2.1 expect概述
expect是建立在tcl语言基础上的一个工具,它可以让一些需要交互的任务自动化地完成,相当于模拟了用户和命令行的交互操作。expect是用来进行自动化控制和测试的工具。主要解决shell脚本中不可交互的问题。对于大规模的Linux运维很有帮助。在Linux运维和开发中,经常需要远程登录服务器进行操作,登录的过程是一个交互的过程,可能会需要输入yes/no,password等信息。为了模拟这种输入,可以使用expect脚本。
在实际的生产环境中,有一个常用的场景就是批量配置集群无密钥登录。如果集群的机器数量很多,手动一台一台地去每台机器去配置无密钥是非常糟糕的事情。使用expect功能,可以远程登录机器,并通过交互方式进行无密钥登录。
5.2.2 except 安装
Linux 系统自身并没有安装expect和tcl,需要手动安装。CentOS 7.3光盘中默认包含expect安装包,所以需要先挂载光盘,制作本地yum仓库,然后通过yum安装expect。安装过程中,yum会自动安装expect的依赖软件tcl。具体安装步骤如下。
(1)挂载光盘
通过mount命令挂载光盘到本地的/media目录
(2)制作本地 YUM源
进入/etc/yum.repos.d/目录,删除默认存在的所有仓库配置文件,新建文件,并命名为local.repo,其中后缀.repo是必须的。配置文件内容如下。
[root@localhost ~]# vim /etc/yum.repos.d/local.repo
name=localrepo
baseurl=file:///media
gpgcheck=0
编写完配置文件后,执行以下命令删除yum缓存并更新。
[root@localhost ~]# yum clean all
[root@localhost ~]# yum make cache
(3)执行安装命令
执行以下命令,通过yum安装expect软件。
[root@localhost ~]# yum install -y expect
5.2.3 基本命令介绍
(1)脚本解释器
expect脚本中首先引入文件,表明使用的是哪一个shell。
#!/usr/bin/expect
(2) expect/send
expect命令用来判断上次输出结果里是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回,只能捕捉由spawn启动的进程的输出。expect 接收命令执行后的输出,然后和期望字符串匹配,若匹配成功则执行相应的send向进程发送字符串,用于模拟用户的输入。Send发送的命令不能自动回车换行,一般要加\r(回车)。其常见语法形式有以下三种。
方式一
expect "$case1" {send "$respond1\r"}
方式二
expect "$case1"
send "$response1\r"
方式三
expect 支持多个分支。
expect
"Scase1" {send "$response1Vr"}
"Scase2" {send "$response2\r"}
"Scase3" {send "$response3\r"}
上述语法结构中$case1代表检测命令的输出结果,如果输出内容和$case1一致,通过send命令模拟用户发送内容到终端。
(3) spawn
spawn 后面通常跟一个命令,表示开启一个会话、启动进程,并跟踪后续交互信息。其语法如下所示。
spawn Linux 执行命令
例如,如果想要跟踪切换用户的交互信息,可以执行以下命令。
spawn su root
(4)结束符
> expect eof:等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了。
> interact:执行完成后保持交互状态,把控制权交给控制台,这时可以手动输入信息。
需要注意的是,expect eof 与 interact 只能二选一。
(5) set
expect默认的超时时间是10秒,通过set命令可以设置会话超时时间,若不限制超时
时间则应设置为-1。例如执行以下命令即可将超时时间设置为30秒。
set timeout 30
(6) exp_continue
exp_continue 表示允许expect继续向下执行指令。
(7) send_user
send_user表示回显命令,相当于echo。
(8)接收参数
expect脚本可以接受从bash传递的参数,使用[lindex Sargv n]获得。其中n从0开始,分别表示第一个,第二个,第三个 .... 参数。参数存在argv中,使用第一个参数如下:
set param0 [lindex $argv 0]
Sargc表示参数个数,判断语句如下:
if ($argc< 1) {
#do something
send_user "usage: $argv0 <param1><param2> ... *
exit
}
在上述脚本中,$argv0 是脚本名,但[lindex Sargv 0]是第一个参数 param1,[lindex
Sargv 1]是第二个参数 param2,以此类推。send_user用来显示信息到父进程(一般为用户
的shell)的标准输出。
5.2.4 expect 语法
1. 语法结构
(1)单一分支语法
单一分支用于简单的用户交互,当监控命令的标准输出满足expect指定的字符串时,
向标准输入发送send指定的字符串。具体用法如下所示。默认情况下,send不会向标准
输入发送回车键,所以需要通过\r手动换行。
expect "password: " {send "mypasswordv"}
(2)多分支模式语法
多分支用于复杂的用户交互,一般情况下输出内容可能有多个,根据不同的输出内容,
分别向标准输入发送不同的内容。其语法格式如下所示,只要匹配了aaa、bbb或ccc中的
任何一个,就执行相应的send语句,然后退出该expect语句。
expect
{
"aaa" {send "AAAVr]
"bbb" {send "BBBV"}
"ccc" {send "CCCV"}
}
除了上述的多分支结构之外,还有另外一种多分支结构,具体使用方法如下所示。exp_continue表示继续后面的匹配,假如配了aaa,执行完send 语句后还要继续向下匹配bbb.
expect
{
"aaa" {send "AAA";exp_continue}
"bbb" {send "BBB";exp_continue }
"ccc" {send "CCC"}
}
2.expect 执行方式
(1)直接执行
通过SSH方式登录远程服务器,需要输入用户名和密码,比较繁琐。如果服务器比较
多,手动输入用户名和密码会耗费大量时间,expect命令可以实现自动登录远程服务器,
并进入交互模式。
[root@localhost ~]# more direct.sh
#!/usr/bin/expect
set timeout 60
log_file test.log
log_user 1
set hostname [lindex $argv 0]
set password [lindex $argv 1]
spawn ssh root@${hostname}
expect {
"(yes/no)"
{send "yesr"; exp_continue}
"*password"
{send "Spasswordr"}
}
interact
[root@localhost ~]# chmod +x direct.sh
[root@localhost ~]# ./direct.sh 127.0.0.1 123456
(2)嵌入执行
上面讲到的直接执行的方式需要expect命令去执行脚本,在编写Shell脚本的时候需
要去调用expect脚本,使用不灵活。这种情况下,可以采用嵌入执行模式,将expect过程
融入Shell当中,方便执行和处理。