• Linux Shell 自动交互功能实现


    1. EOF 多文本输入

    需求案例 1

    新交付了一批机器,每台机器只分配了一块落盘 ,现在根据需求对该盘进行分区并实现挂载,如何实现?

    需求分析:

    对于一个盘,实现分区挂载到不同目录,通常思路有两条:

    方法一: 将整块盘作为一个PV ,整合成VG卷,再根据划分不同LV卷大小分给不同目录方法二: 通过fdisk 将盘直接分割成对应需求的大小,再对磁盘初始化,完成挂载

    方案解决

    这里我们为了演示交互功能,选择方法二,实现脚本如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    #!/bin/bash

    fdisk /dev/sdb <

    n

    p

    1

    wq

    EOF

      

     mkfs.xfs /dev/sdb1 &&  mkdir -p /data && mount /dev/sdb1 /data

    echo '/dev/sdb1 /data xfs defaults 0 2' >> /etc/fstab

    分析上述脚本,我们发现使用了 一个关键字 EOF

    • EOF是END Of File的缩写,表示自定义终止符.既然自定义,那么EOF就不是固定的,可以随意设置别名,在linux按ctrl-d就代表EOF.
    • EOF一般会配合cat能够多行文本输出.

    其用法如下:

    <

    .... //需要输入的内容

    EOF //结束

    例如使用 cat、<<、EOF>以交互方式编写bash脚本,如下所示。

    1

    2

    3

    4

    5

    6

    cat << EOF > script.sh

    #!/bin/bash

      

    printf "Hello\n"

    printf "Wordl!\n"

    EOF

    合理 利用这三个,即可以完成对应多文本交互输入,例如修改用户密码,正常情况下,需要连续输入两次密码,两次密码一致才能修改成功,如下:

    上面我们学会了EOF 这个关键字,那么我们试试通过它来修改密码。脚本如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    #!/bin/bash

      

    cat << EOF| passwd

    新密码

    新密码,与上述需一致

    EOF

      

    # or 不使用管道符

      

    passwd << EOF

    新密码

    新密码,与上述需一致

    EOF

    2. Expect 自动交互

    需求案例 2

      新交付了一批机器,需要给每台机器分发文件,如何实现?

    需求分析:

    远程拷贝文件常用密令是scp 或者 rsync ,但是在给每台机器传输时需要若输入密码,有的机器可能还需要输入YES,录入机器指纹信息,如下:

    Expect 是在tcl基础上的一个自动化交互套件, 在一些需要交互输入指令的场景下, 可通过脚本设置自动进行交互通信. 其交互流程主要有以下5步:

    0 定义变量

    1 spawn启动指定脚本或命令

    2 expect匹配结果关键词

    3 send针对指定关键词发送指定指令

    4 执行完成, 退出

    但可惜的是os默认没有安装,因此需要先安装才能使用

    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.

    方案解决:

    1. 先检查本机是否安装了expect ,如果没有安装,需要手动安装

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    # 检查是否安装了expect:

    [root@localhost ~]# rpm -qi expect

    Name        : expect

    Version     : 5.45

    Release     : 14.el7_1

    Architecture: x86_64

    Install Date: Fri 05 Aug 2022 07:26:04 AM CST

    Group       : Development/Languages

    ....

      

    # 如果没有安装, 使用yum安装expect ,通常会顺带把依赖包tcl 也安装了:

    [root@localhost ~]# yum install -y expect  # -y  其实也是安装过程中一个交互,发现没,只是作为参数传入了

    [root@localhost ~]# yum install -y tcl  # 如果上述命令提示已安装tcl了,此步可以忽略

      

    # 查看expect的安装路径:

    [root@localhost ~]#  which expect

    /usr/bin/expect

    2 .对应功能脚本开发,本案例脚本参考如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    [root@test01 ~]# cat scp.exp

    #! /usr/bin/expect

    set file [lindex $argv 0]

    set file2 [lindex $argv 1]

    spawn scp -rp $file $file2 root@192.168.31.89:/tmp

    expect {

     "(yes/no)" {send "yes\r";exp_continue}

     "*password:*" {send "Password\r"}

      

    }

    expect eof

    exit -onexit {

     send_user "bye \n"

    }

    3. 分析上述脚本,有几个点需要说明

    1

    #!/usr/bin/expect

    脚本文件的第一行指明expect 安装位置,具体可以参考2 中命令查看,指明脚本解析器,和Shell类似,表示程序使用Expect解析,这里与一般bash 脚本不同,因此需要注意,通常我们会将expect脚本后缀修改成exp来和bash 脚本 sh区别

    set 设置变量值

    set file [lindex $argv 0] 将传入的第一个参数赋给file ,类似第二、三个参数[lindex $argv 1] [lindex $argv 2] 等,后续调用时使用 $file ,和shell 一样。特殊参数:

    $argc表示传参的个数,$argv0表示脚本的名字

    spawn 表名要执行的脚本或程序命令,如ssh、scp等

    格式: spawn [选项] [需要自动交互的命令或程序]

    例如:spawn scp -rp $file $file2 root@192.168.31.89:/tmp #<==执行scp命令(注意开头必须要有spawn, 否则无法实现交互)

    expect

    需和spawn 配合使用 ,表示匹配spawn指定的脚本或命令的输出结果,如果与expect后面的字符串匹配,就执行下面的send命令,表示对结果响应反馈

    有时命令的输出提示信息有可能会变化,所以可以在expect中使用模糊匹配,比如*

    注意:匹配的动作也可以放在下一行,这样就不需要使用{}(大括号)了

    send

    在expect命令匹配指定的字符串后,发送指定的字符串给系统,这些命令可以支持一些特殊转义符号,例如:\r表示回车、\n表示换行、\t表示制表符等

    exp_continue

    从命令的拼写就可以看出命令的作用,即让Expect程序继续匹配的意思,如果需要一次匹配多个字符串,那么不同的匹配之间就要加上exp_continue,否则expect将不会自动输入指定的字符串。最后一个的结尾就不需要加上exp_continue了,因为前面都已完成了,它是最后一个啦

    exit

    功能类似于Shell中的exit,即直接退出脚本,还可以利用这个命令对脚本做一些关闭前提示等工作

    send_user

    打印Expect脚本信息,类似Shell里的echo. 例如打印变量信息,验证数据传入是否正常

    在掌握expect 基本使用方式后,我们写一个批量查看机器负载信息的小脚本,加强记忆

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    #! /usr/bin/expect

        set time 30

        set ip [lindex $argv 0]

      

        spawn ssh root@$ip uptime

        expect {

            "*yes/no" { send "yes\r"; exp_continue }

            "*password:" { send "$password\r" }

        }

        expect eof

    小试牛刀

    在学习完以上两个方法,我们试着写一个脚本,结合上述两种方式,批量查看各机器目录挂载情况,并列举出来,参考脚本如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    #!/bin/bash

      

    ip="192.168.31.89"

    username="root"

    password="123456"

    cmd=" df -PTh|grep ^/dev"

    # 指定执行引擎

    expect <

        set time 30

        spawn ssh $username@$ip  $cmd

        expect {

            "*yes/no" { send "yes\r"; exp_continue }

            "*password:" { send "$password\r" }

        }

        expect eof

    EOF

    以上两种方式就是日常在Linux Shell 脚本常用来做自动化部署,解决脚本执行过程参数交互问题,尤其expect 配合一些shell脚本执行,十分便捷。除了以上使用方式,在企业生产中,我们还会用到ansible 脚本,ansible是新出现的自动化运维工具,基于Python开发,通过调用其模块,实现批量系统配置、批量程序部署、批量运行命令等功能,有兴趣的小伙伴可以试试学习下。

  • 相关阅读:
    PHP 运行 mkdir() Permission Denied 的原因
    最新版 Let’s Encrypt免费证书申请步骤,保姆级教程
    gcc编译器
    英伟达发布世界最大芯片Blackwell GPU:开启AI计算新纪元
    MySQL 日志及数据备份
    Spring中有哪些情况会导致@Bean注入失效呢?
    vue 点击事件失效检查办法
    备战金九银十!!! 互联网Java岗面试手册,收藏=offer拿到手软!!
    antd表格宽度超出屏幕,列宽自适应失效
    浏览器检测麦克风音量
  • 原文地址:https://blog.csdn.net/jh035/article/details/127980265