05 Shell编程之免交互

目录

[5.1 Here Document 免交互](#5.1 Here Document 免交互)

[5.1.1 Here Document 概述](#5.1.1 Here Document 概述)

[5.1.2 Here Document 免交互](#5.1.2 Here Document 免交互)

[1. 通过read命令接收输入并打印](#1. 通过read命令接收输入并打印)

[5.1.3 Here Document变量设定](#5.1.3 Here Document变量设定)

[5.1.4 Here Document 格式控制](#5.1.4 Here Document 格式控制)

(1)关闭变量替换的功能。

(2)去掉每行之前的TAB字符。

[5.1.5 Here Document 多行注释](#5.1.5 Here Document 多行注释)

5.2expect免交互

[5.2.1 expect概述](#5.2.1 expect概述)

[5.2.2 except 安装](#5.2.2 except 安装)

(1)挂载光盘

[(2)制作本地 YUM源](#(2)制作本地 YUM源)

(3)执行安装命令

[5.2.3 基本命令介绍](#5.2.3 基本命令介绍)

(1)脚本解释器

[(2) expect/send](#(2) expect/send)

[(3) spawn](#(3) spawn)

(4)结束符

[(5) set](#(5) set)

[(6) exp_continue](#(6) exp_continue)

[(7) send_user](#(7) send_user)

(8)接收参数

[5.2.4 expect 语法](#5.2.4 expect 语法)

[1. 语法结构](#1. 语法结构)

(1)单一分支语法

(2)多分支模式语法

[2.expect 执行方式](#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当中,方便执行和处理。

相关推荐
Ztiddler5 小时前
【Linux Shell命令-不定期更新】
linux·运维·服务器·ssh
小小不董5 小时前
Oracle OCP认证考试考点详解082系列16
linux·运维·服务器·数据库·oracle·dba
IPdodo全球网络5 小时前
如何利用静态住宅IP优化Facebook商城的网络稳定性与运营效率
运维·服务器
a1denzzz5 小时前
Linux系统的网络设置
linux·服务器·网络
运维&陈同学6 小时前
【模块一】kubernetes容器编排进阶实战之k8s基础概念
运维·docker·云原生·容器·kubernetes·云计算
m0_519523106 小时前
Linux——简单认识vim、gcc以及make/Makefile
linux·运维·vim
mit6.8246 小时前
[Docker#4] 镜像仓库 | 部分常用命令
linux·运维·docker·容器·架构
zyp2468107 小时前
Linux之DNS服务器
linux·运维·服务器
wdxylb7 小时前
将C++搭建的简单HTTP服务器升级为 HTTPS 服务器
运维·服务器·https
Denzel张7 小时前
ubuntu_dpkg_dep_list
linux·运维·ubuntu