shell脚本之免交互

614 阅读5分钟

使用shell脚本时,经常会出现用户与脚本交互的时候,一般我们都是通过在终端内完成交互,也就是全字符界面。(Here Document)免交互是标准输入的一种替代品可以帮助脚本开发人员不必使用临时文件来构建输入信息,而是直接就地生产出一个"文件"并用作"命令"的标准输入。
使用I/O重定向的方式将命令列表提供给交互式程序。
常用的交互程序有read,ftp,passwd,su,sudo。cat也可配合免交互的方式重定向输出到文件。

免交互(Here Document)基本用法

免交互(here document)格式

命令 <<标记
...
(内容) #标记之间是传入内容
...
标记

使用注意事项

  • 标记可以使用任意合法字符,但开始标记与结尾标记需要保持一致。(常用标记EOF,使用其他字母也可以)
  • 结尾的标记一定要顶格写,前面不能有任何字符。
  • 结尾的标记后面也不能有任何字符(包括空行)。
  • 开头标记前后的空格会被省略掉

通过read命令接收输入并打印
read只能读取一行内容,只要遇到换行符就中止读取

[root@localhost ~]#read a <<EOF
> hello world
> EOF
[root@localhost ~]#echo $a
hello world
[root@localhost ~]#read a <<EOF
> hello
> world
> EOF
[root@localhost ~]#echo $a
hello

read.png 统计输入的行数,免交互实现,将内容置于标记“EOF”之间
将输入的内容传给wc命令

[root@localhost ~]#wc -l <<EOF
> 11
> 22
> 33
> 44
> EOF
4
[root@localhost ~]#wc -l <<aaa
> 11
> 22
> 33
> 44
> EOF
> aaa
5
[root@localhost ~]#wc -l <<EOF
> 11
> 22
> 33
>  EOF
> EOF
4

wc.png

示例

通过passwd给用户设置密码

[root@localhost ~]#
[root@localhost ~]#useradd wry
[root@localhost ~]#passwd wry <<EOF
> ROOT123
> ROOT123
> EOF
更改用户 wry 的密码 。
新的 密码:无效的密码: 密码未通过字典检查 - 过于简单化/系统化
重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]#

密码.png

cat打印和免交互一起使用

[root@localhost ~]#cat <<EOF >hello.txt
> hello
> this is wenjian
> EOF
[root@localhost ~]#cat hello.txt 
hello
this is wenjian

cat.png

Expect

ecpect是建立在tcl语言基础上的一个工具,常被用于进行自动化控制和测试,常用于解决shell脚本中交互相关的问题。
我们可以用rpm -q expect;rpm -q tcl 来查看本机上是否有expect工具。

expect基本命令用法

  1. 脚本解释器
    expect脚本中首先引入文件,表明使用的是哪一个shell。
    #!/usr/bin/expect
  2. spawn启动进程,跟踪信息
    spawn 后面通常跟一个linux执行命令,表示开启一个会话,启动进程,并跟踪后续交互信息。
    eg:spawn passwd root
  3. expect接受字符串
    判断上次输出结果中是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回;
    只能捕捉由 spawn 启动的进程的输出;
    用于接收命令执行后的输出,然后和期望的字符串匹配
  4. send发送字符串
    向进程发送字符串,用于模拟用户的输入;
    该命令不能自动回车换行,一般要加\r (回车)或者\n
方法一:
expect “密码” {send123456\r”}              同一行send部分需要加{}

方法二:
expect "密码"
send123456/r”                             换行send不需要加{}

方法三:(expect支持多分支)
expect
{
“密码1”  {send123457\r”}
“密码2”  {send "123458\r"}        只要执行了其中一种情况后,执行的相应的send语句后会退出expect结构
“密码3”  {send "123456\r"}
}
复制代码
  1. 结束符(expect eof 与 interact 只能二选一)
  • expect eof
    表示交互结束,等待执行结束,退回到原用户,与spawn对应。 比如切换到root用户,expect脚本默认的是等待10s当执行完命令后,默认停留10s后,自动切回了原用户
  • interact
    执行完后保持交互状态,把控制权交给控制台会停留在目标终端而不会退回到原终端,这个时候就可以手工操作了,interact后的命令不起作用;
    例如:interact后添加exit,并不会退出root用户。而如果没有interact则登录完成后会退出,而不是留在远程终端上。
    使用interact会保持在终端而不会退回到原终端;
    例如:切换到root用户,会一直在root用户状态下;比如ssh到另外一台服务器,会一直在目标服务器终端,而不会切换到原来服务器
  1. set 设置会话超时时间
    expect 默认的超时时间是10秒,通过set 命令可以设置会话超时时间,若不限制超时时间则应设置为-1
  2. exp_continue
    exp_continue 附加于某个 expect 判断项之后,可以使该项被匹配后,还能继续匹配该 expect 判断语句内的其他项。
    exp_continue 类似于控制语句中的 continue 语句。表示允许 expect 继续向下执行指令。
    并行执行,exp_continue 前面的匹配如果有就执行,没有就不执行;但后面的一定会执行。
  3. send_users
    表示回显命令,相当于echo
  4. 接收参数
    expect 脚本可以接受从bash命令行传递参数,使用 [lindex $argv n]获得。其中你从0开始,分别表示第一个,第二个,第三个.....参数
set hostname [lindex $argv 0]    相当于hostname=$1
set passwd   [lindex $argv 1]    相当于passwd=$2

示例

ssh免交互远程登陆

第三题代码.png

远程登陆.png