温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Shell免交互如何实现

发布时间:2022-07-19 13:44:06 来源:亿速云 阅读:129 作者:iii 栏目:开发技术

这篇文章主要介绍“Shell免交互如何实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Shell免交互如何实现”文章能帮助大家解决问题。

    一、Here Document

    1.Here Document概述

    使用 I/O 重定向的方式将命令列表提供给交互式程序或命令,比如 ftp、cat或read命令。
    HereDocument是标准输入的一种替代品,可以帮助脚本开发人员不必使用临时文件来构建输入信息,而是直接就地生产出一个文件并用作命令的标准输入。

    2.基本语法格式

    命令 <<标记
    &hellip;&hellip;
    &hellip;&hellip;
    标记

    #特殊字符“<<”在标记和命令之前,这样做的目的是将命令块的输出重定向到程序和命令的stdin。
    #标记的选择要确保不会出现在其他地方,避免出现混淆;两个标记之间的内容被当做是一个文件并用作“命令”的标准输入。
    #另外Here Document也可以与非交互式程序和命令一起使用

    四点注意事项:

    • 标记可以使用任意的合法字符;

    • 结尾的标记一定要顶格写,前面不能有任何字符;

    • 结尾的标记后面也不能有任何字符(包括空格);

    • 开头的标记前后的空格会被省略

    [root@c7-1 ~]# cat <<EOF   //直接把输入的从命令行输出
    > hello world
    > EOF
    hello world
    
    [root@c7-1 ~]# cat > name <<EOF   //输入保存到文件
    > liuchun
    > zhougang
    > EOF
    
    [root@c7-1 ~]# cat name
    liuchun
    zhougang
    
    
    [root@c7-1 ~]# cat >> name <<EOF    //追加输入保存到文件
    > liufei
    > EOF
    
    [root@c7-1 ~]# cat name 
    liuchun
    zhougang
    liufei

    例:创建yum源

    [root@c7-1 ~]# cat > test.repo <<EOF
    > [test]
    > name=test
    > baseurl=file:///mnt
    > enabled=1
    > gpgcheck=0
    > EOF
    
    另外写法1 cat <<EOF > local.repo
    另外写法2 tee test1.txt <<EOF

    3.Here Documen免交互

    3.1 通过 read 命令接收输入并打印,输入值是两个 EOF 标记之间的部分,也就是“10”,这将作为变量 a 的值

    [root@c7-1 ~]# read a <<EOF
    > 10
    > EOF
    [root@c7-1 ~]# echo $a
    10

    3.2 通过 passwd 给用户设置密码

    [root@c7-1 ~]# passwd zhangsan <<EOF
    > 123456
    > 123456
    > EOF
    更改用户 zhangsan 的密码 。
    新的 密码:无效的密码: 密码少于 8 个字符
    重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。

    4.变量设定(支持变量替换)

    4.1 在写入文件时要先将变量替换成实际值,在结合 cat 命令完成写入

    例1:

    [root@localhost ~]# aa=$(cat <<EOF    //变量替换
    > $a
    > EOF
    > )
    
    echo $aa

    例2:

    #!/bin/bash 
    doc_file="123.txt" 
    i="123"
    cat > $doc_file << EOF 
    Welcome to  $i 
    EOF
    
    this is $i 
    cat 123.txt

    4.2 整体赋值给一个变量,然后通过 echo 命令将变量值打印出来

    #!/bin/bash 
    ivar="Great! Beautyful!"
    myvar=$(cat <<EOF     #将Here Document 整体赋值给变量
    This is Line 1.
    That are Sun,Moon and Stars.
    $ivar       #输出时会进行变量替换
    EOF
    )
    echo $myvar

    5.格式控制

    5.1 关闭变量替换的功能

    [root@c7-1 ~]# aa=$(cat <<'EOF'    //关闭变量替换 对标记加单引号,即可关闭变量替换
    20
    $a
    EOF
    )
    echo $aa
    
    
    #!/bin/bash
    cat <<'EOF'        //对标记加单引号,即可关闭变量替换
    This is Line 1.
    $kkk 
    EOF

    5.2 去掉每行之前的 TAB 字符

    在第一行的标记前面加&lsquo;-&rsquo;,这个表示要抑制各行首 TAB 的作用。

    [root@c7-1 ~]# vim dome3.sh    //写一个脚本测试抑制tab键输出
    
    #!/bin/bash
    cat <<EOF
            hello world
    EOF
    
    cat <<-EOF                //加 - 去除tab
            hello world
    EOF
    
    [root@c7-1 ~]# bash tab.sh 
        hello world
    hello world

    6.多行注释

    Bash 的默认注释是“#”,该注释方法只支持单行注释,在 Shell 脚本的工作中,“#”右侧的任何字符串,bash 都会将其忽略。Here Document 的引入解决了多行注释的问题。
    : 代表什么都不做的空命令。中间标记区域的内容不会被执行,会被bash 忽略掉,因此可达到批量注释的效果。

    #!/bin/bash
    : <<-EOF                //多行注释 以 :开头的Here Document标记内容不会被执行
    the second comment.
    test line. 
    EOF
    echo "dashiji"

    二、Expect

    1.Expect概述

    建立在tcl语言基础上的一个工具,常被用于进行自动化控制和测试,解决shell脚本中交互相关的问题

    2.expect的基本安装

    expect是一个程序,所以他也是需要提前安装才可以使用的

    [root@c7-1 expect]# rpm -q expect
    [root@c7-1 expect]# rpm -q tcl        
    [root@c7-1 expect]# yum install expect -y    //安装expect时会把tcl作为依赖包安装

    3.基本命令

    (1)脚本解释器

    expect脚本中首先引入文件,表明使用的是哪一个shell
    #!/usr/bin/expect

    (2)spawn

    spawn后面通常跟一个Linux执行命令,表示开启一个会话、启动进程,并跟踪后续交互信息。
    例如:

    spawn passwd root

    (3)expect

    判断上次输出结果中是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回;
    只能捕捉由spawn启动的进程的输出;
    用于接收命令执行后的输出,然后和期望的字符串匹配

    (4)send向进程发送字符串,用于模拟用户的输入;该命令不能自动回车换行,一般要加 \r (回车) 或者 \n

    方式一:
        expect "密码"{ send "abc123\r" }        //同一行send部分要有{}
    
    方式二:
        expect "密码"
        send "abc123\r"                        //换行send部分不需要有{}
    
    方式三:
        expect支持多个分支
        expect        //只要匹配了其中一个情况,执行相应的send语句后退出该expect语句
        "密码1"{ send "abc123\r" }
        "密码2"{ send "123456\r" }
        "密码3"{ send "123123\r" }

    (5)结束符

    expect eof
    表示交互结束,等待执行结束,退回到原用户,与spawn对应。
    比如切换到root用户,expect脚本默认的是等待10s,当执行完命令后,默认停留10s后,自动切回了原用户

    interact
    执行完成后保持交互状态,把控制权交给控制台,会停留在目标终端而不会退回到原终端,这个时候就可以手工操作了,interact后的命令不起作用,比如interact后添加exit,并不会退出root用户。而如果没有interact则登录完成后会退出,而不是留在远程终端上。

    注意:expect eof 与 interact 只能二选一。

    (6)set

    expect 默认的超时时间是10秒,通过 set命令可以设置会话超时时间,若不限制超时时间则应设置为-1。
    例: 

    set timeout 30

    (7)exp_continue

    附加于某个expect判断项之后,可以使该项被匹配后,还能继续匹配该expect-判断语句内的其他项。exp_continue类似于控制语句中的continue 语句。表示允许expect继续向下执行指令。

    例如:下例将判断交互输出中是否存在yes/no 或*password。如果匹配 yes/no 则输出 yes并再次执行判断;
    如果匹配*password则输出abc123并结束该段expect语句。

    expect{
        "(yes/no)"
        { send "yes\r";exp_continue;}
        "*password"
        { set timeout 300;send "abc123\r";}
    }
    #注意:使用exp continue时,如果跟踪像passwd这样的输入密码后就结束进程的命令,expect{}外不要再加上expect eof
    #因为spawn进程结束后会默认向expect发送eof,会导致后面的expect eof执行报错
    
    #注:表示允许用户进行交互操作,一直保持回话连接

    (8)send user

    send user 表示回显命令,相当于echo

    (9)接收参数

    expect脚本可以接受从bash命令行传递的参数,使用[lindex $argvn]获得。
    其中n从o开始,分别表示第一个,第二个,第三个..参数。例:

    set hostname [ lindex $argy 0 ]

    相当于hostname=$1

    set password [ lindex $argy 1 ]

    相当于password=$2

    4.用expect编写脚本

    4.1 ssh无交互登录到远程服务器

    [root@c7-1 expect]# vim dome1.sh 
    
    #!/usr/bin/expect                //这里需要用expect自己的解释器,注意不要写成bash否则无法识别
    
    spawn ssh root@192.168.3.100    //开启一个程序,这个程序是ssh远程登录            
    
    expect {                        //捕获内容,当出现password的时候,就会向程序发送密码,默认是不换行的,所以需要\r回车换行,多个条件需要花括号括起来,注意格式问题!
            "password"
            { send "123\r"; }        
    }
    
    interact

    4.2 如果想要在对方服务器上进行一下操作后再退出可执行以下脚本

    [root@c7-1 ~]# vim expect.sh
    #!/usr/bin/expect
    
    spawn ssh root@192.168.3.100
    
    expect {
            "password:"
            { send "123456\r"; }
    }
    
    
    expect "#"       //当捕获到#的时候
    send "ls\r"    //执行ls命令
    send "ifconfig ens33\r"   //执行ifconfig ens33命令
    send "exit\r"   //执行完exit退出登陆
    
    expect eof    //不需要进行交互了,意味着结束expect程序,如果不写的话不会执行操作直接退出;如果不写,写interact也无法在对方机器上执行命令,eof可以替换

    4.3 定义和引用变量

    用set关键字定义变量,变量名和变量的值中间用空格分开,其他用法与shell脚本一致

    #!/usr/bin/expect
    set user root
    set ip 192.168.3.100
    set pass 123456
    
    #引用位置变量
    #!/usr/bin/expect
    set user root
    set ip [lindex $argv 0]    //设置第一个位置变量为ip
    set pass [lindex $argv 1]   //设置第二个位置变量为登陆密码
    
    spawn ssh $user@$ip
    
    expect {
            "password:"
            { send "$pass\r"; }
    }
    
    
    expect "#"
    send "ls\r"
    send "ifconfig ens33\r"
    send "exit\r"
    
    expect eof
    
    [root@c7-1 ~]# ./expect sh 192.168.3.100 123456   //执行时需要加位置变量
    
    #####还可以定义其他参数,例如超时时间,日志等
    #超时时间
    set timeout 20   //登陆超时多少秒退出
    #开启日志文件
    log_file test.log   //日志记录操作
    #显示信息
    log_user 1   //1为屏幕输出信息,0为不输出

    4.4 在shell脚本中调用expect

    #!/bin/bash
    username=$1
    
    useradd $username
    
    /usr/bin/expect <<-EOF
    
    spawn passwd $username
    expect {
            "新的 密码"     //注意:获取的内容和发送的内容不能在同一行否则执行不成功
            {send "123456\r";exp_continue}
            
            "重新输入新的 密码"
            {send "123456\r";}
    }
    EOF
    
    验证结果:
    [root@c7-1 ~]# ./user.sh wangwu
    spawn passwd wangwu
    更改用户 wangwu 的密码 。
    新的 密码:
    无效的密码: 密码少于 8 个字符
    重新输入新的 密码:
    passwd:所有的身份验证令牌已经成功更新。

    关于“Shell免交互如何实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI