Shell编程----Expect免交互

Shell编程----Expect免交互&标记法免交互

文章目录

  • Shell编程----Expect免交互&标记法免交互
  • 前言
  • 一: Here Document 免交互
      • 1.1:什么是Here Document?
      • 1.2: Here Document 概述
      • 1.3: Here Document 使用注意事项
      • 1.4: Here Document免交互
      • 1.5: Here Document 变量设定
      • 1.6: Here Document 格式控制
      • 1.7: Here Document 多行注释
  • 二:Expect概述
  • 三:Expect基本命令
      • 3.1:Expect安装
      • 3.2: Expect流程-命令
      • 3.3:基本命令(expect内容命令)
      • 3.4:基本命令(expect其他命令)
  • 四:Expect执行方式
      • 4.1:Expect语法
      • 4.2:Expect直接执行(以ssh为例)
      • 4.3:Expect嵌入执行(以ssh为例)
      • 4.4:Expect脚本命令总结
  • 五:Expect实操
      • 5.1:创建用户,免交互设密码
      • 5.2:SSH自动登录
      • 5.3 : FTP免密 登陆

前言

一: Here Document 免交互

1.1:什么是Here Document?

  • Here document (here-document, here-text, heredoc, hereis, here-string, here-script)是一个文件文字或输入流文字:它是源代码文件的一部分,被视为它是一个单独的文件。该术语还用于使用类似语法,保留换行符和文本中的其他空格(包括缩进)的多行字符串文字形式。

1.2: Here Document 概述

  • 使用I/O重定向的方式将命令列表提供给交互程序

  • 标准输入的一种替代品

  • 语法格式

    命令 <<标记
    ...
    ...
    标记
    

1.3: Here Document 使用注意事项

  • 标记可以使用任意合法字符
  • 结尾的标记一定要顶格写,前面不能有任何字符
  • 结尾的标记后面也不能有任何字符(包括空格)
  • 开头标记前后的空格会被省略掉

1.4: Here Document免交互

  • 通过read 命令接受输入并打印

    [root@shell ~]# vim b.sh
    #!/bin/bash
    read i <echo $i
    [root@shell ~]# chmod +x b.sh 
    [root@shell ~]# ./b.sh 
    hello world
    
  • 通过paswd给用户设置密码

    [root@shell ~]# vim passwd.sh
    #!/bin/bash
    useradd zhangsan
    passwd zhangsan <[root@shell ~]# chmod +x passwd.sh 
    [root@shell ~]# ./passwd.sh 
    更改用户 zhangsan 的密码 。
    新的 密码:无效的密码: 密码少于 7 个字符
    重新输入新的 密码:passwd:所有的身份验证令牌已经成功更新。
    

1.5: Here Document 变量设定

  • 变量替换

    [root@shell ~]# vim filename.sh
    #!/bin/bash
    filename="test.txt"
    school="kgc"
    cat > $filename <$school .com
    EOF
    [root@shell ~]# chmod +x filename.sh 
    [root@shell ~]# ./filename.sh 
    [root@shell ~]# ls
     test.txt
     .....
    [root@shell ~]# cat test.txt 
    this is kgc .com
    
  • 变量设定

    [root@localhost ~]# vim here_var_set.sh
    #!/bin/bash
    ivar="Great! Beautyful!"
    myvar=$(cat <.
    That are Sun,Moon and Stars.
    $ivar
    EOF 
    )
    echo $myvar
    [root@localhost ~]# sh here_var_set.sh
    This is Line 1. That are Sun,Moon and Stars. Great! Beautyful!
    

1.6: Here Document 格式控制

  • 关闭变量替换功能

    [root@localhost ~]# cat here_format_shut.sh
    #!/bin/bash
    cat <<'EOF'                       #单引号关闭变量替换
    This is Line 1.
    $kgc
    EOF
    [root@localhost ~]# sh here_format_shut.sh
    This is Line 1.
    $kgc                              #变量当成普通字符输出
    
  • 去除每行之前的TAB字符

    [root@localhost ~]# vim here_format_tab.sh
    #!/bin/bash
    cat <<-'EOF'                        #"-"表示抑制行首的TAB作用
    	This is Line 1. 
    	$kgc
    EOF
    [root@localhost ~]# sh here_ format _tab.sh
    Thisis Line 1.
    $kgc
    

1.7: Here Document 多行注释

  • 通过Here Document 方式使Bash支持多行注释

  • 语法格式

    :<< DO-NOTHING
    第一行注释
    第二行注释
    ....
    DO-NOTHING
    

    标记符之间的内容表示注释内容

    #! /bin/bash
    : <echo "hello"
    echo "world"
    DOING
    cat <<-'EOF'
    	this is
    	$school . com
    EOF
    [root@shell ~]# bash nothing.sh 
    this is
    $school .com
    #注释的内容不显示
    

二:Expect概述

  • Expect是建立在tcl基础上的一个工具,Expect是用来进行自动化控制和测试的工具。主要解决shell脚本中不可交互的问题,对于大规模的linux运维很有帮助

  • 在Linux运维和开发中,我们经常需要远程登录服务器进行操作,在登录的过程是一个交互的过程,可能会需要输入yes/no password等信息。

    为了模拟这种输入,可以使用Expect脚本

三:Expect基本命令

3.1:Expect安装

  • 系统一般不自带,需要自己安装

  • 安装命令

    yum -y install expect
    

3.2: Expect流程-命令

  • spawn:启动进程,并跟踪后续交互信息

  • send:向进程发送字符串,用于模拟用户的输入

    该命令不能自动回车换行,一般要加\r(回车)

  • expect

    expect的一个内部命令,判断上次输出结果里是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回

    只能捕捉有spawn启动的进程的输出

  • 结束符:

    • interact:执行完成后保持交互状态,把控制权交给控制台
    • expect eof: 等待执行结束
spawn ssh root@IP 追踪指令 if条件
expect “connecting (yes/no)”? 捕捉会话 匹配字符串
send yes 自动发送指令 执行

3.3:基本命令(expect内容命令)

  • set

    Timeout:指定超时时间,过期则继续执行后续指令

    • 单位是:秒
    • timeout -1为永不超时
    • 默认情况下,timeout是10秒

    设置日志文件,信息是否展示

  • exp_continue
    允许expect继续向下执行指令

  • send_user
    回显命令,相当于echo

3.4:基本命令(expect其他命令)

  • 接受参数

    • Expect脚本可以接受从bash传递的参数,

    • 可以使用[lindex $argc n]获得,

    • n从0开始,分别表示第一个,第二个,第三个…参数

      [lindex $argv n] 获得参数  相当于$1
      
  • Expect脚本的结尾

    expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了

    expect eof是在等待结束标志。由spawn启动的命令在结束时会产生一个eof标记,expect eof就是在等待这个标记

四:Expect执行方式

4.1:Expect语法

  • 单一分支语法

    expect "password:" {send "mypassword\r"}
    
  • 多分支模式语法第一种

    expect "aaa" {send "AAA\r"}
    expect "aaa" {send "AAA\r"}
    expect "aaa" {send "AAA\r"}
    'send命令不具备回车换行功能,所以需要自己添加\r 或 \n'
    
  • 多分支模式语法第二种

    expect {
    "aaa" {send "AAA\r"}
    "bbb" {send "BBB\r"}
    "ccc" {send "CCC\r"}
    }
    '只要匹配了aaa 或bbb或ccc中的任何一个,执行相应的send语句后就会退出该expect语句'
    
    expect {
    "aaa" {send "AAA\r";exp_continue}
    "bbb" {send "BBB\r";exp_continue}
    "ccc" {send "CCC\r"}
    }
    'exp_continue表示继续后面的匹配,如果匹配了aaa,执行完send语句后还会继续向下匹配bbb'
    '捕捉内容要用双引号引起来'
    'send要写在{}中,输出信息也要用双引号引起来,分号“;”要写在}里面'
    
  • -re参数表示匹配正则表达式

4.2:Expect直接执行(以ssh为例)

  • 其中,$argv 0 代表位置变量$1
    
    $argv 1 代表位置变量$2
    
  • #!/usr/bin/expect 是Expect二进制文件的路径,表示加载预加载环境

    [root@shell~]#ssh a.sh
    #!/usr/bin/expect
      set timeout 60	   '超时时间60S'
      log file test.log    '日志名称test.log,在当前目录下'
      log_user 1           '显示信息'
      set hostname [lindex $argv 0]		'变量定义'
      set password [lindex $argc 1]
      spawn ssh root @$hostname		     '启动spawn'
      expect {			                 '匹配条件'
          "(yes/no)"
          {send "yes\r";exp_continue}
          "*password"
          {send "$password\r"}
      }
    interact		                     '将权限转交控制台'
    

4.3:Expect嵌入执行(以ssh为例)

[root@localhost~]#cat b.sh
#!/bin/bash
  hostname=$1
  password=$2
  /usr/bin/expect<<-EOF           'Expect开始表示'
  spawn ssh root@${hostname}
  expect {
      "(yes/no)"
      {send "yes\r";exp_continue}
      "*password"
      {send "$password\r"}
  }
  expect "*]#"
  send "exit\r"
  expect eof
EOF		                          'Expect结束标志,EOF前后不能有空格'

4.4:Expect脚本命令总结

1: #!/usr/bin/expect -re
  告诉操作系统脚本里的代码使用那一个shell来执
   -re 表示启用正则表达匹配

2. set timeout -1 
   设置超时时长 -1 代表永不过期,默认时10秒

3. exp_continue
   表示循环匹配。匹配到改关键字后继续从头开始匹配。若不加exp_continue则会直接退出

4. expect eof
   匹配结尾 例如执行命令结束时则可以匹配到 eof

5. exit、interact
   exit交互结束退出
   interact表示执行完后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了

6. exp_send/send
   都是想程序发送字符串,有啥区别还没找到
7. send_user
   send_user 命令用来把后面的参数输出到标准输出中去,默人的send、exp_send 命令都是将参    数输出到程序中去的,
8.如何使用
  mac 上直接使用 ./XX.sh 执行上述脚本不行。需要使用 expect XX.sh 才能正确执行

9.调试
expect -d XX.sh输出每次执行的过程可以用于编写脚本时调试之用

五:Expect实操

5.1:创建用户,免交互设密码

  • 使用嵌入式脚本创建(个人推荐使用嵌入式脚本)

    [root@shell ~]# vim useradd.sh 
    #!/bin/bash
    hostname=$1
    password=$2
    useradd $1
    #experct嵌入
    /usr/bin/expect <<-EOF
    spawn passwd ${hostname}
    expect {
       "新的 密码:"
       {send "${password}\r";exp_continue}
       "重新输入新的 密码:"
       {send "${password}\r";}
    }
    expect "*]#"
    send "exit\r"
    expect eof
    
    

5.2:SSH自动登录

  • 首次登录

  • 正常登录

  • 连接被拒绝,可能是ssh没开,或者端口不对,或者防火墙限制

  • 脚本内容

    #!/bin/bash
    hostname=$1
    password=$2
    /usr/bin/expect<<-EOF
      spawn ssh $hostname
      expect {
            "Connection refused" exit
            "Name or service not known" exit
            "to continue" {send "yes\r";exp_continue}
            "password:" {send "$password\r"}
    }
    expect "*]#"
    send "exit\r"
    expect eof
    EOF
    
    '首次登陆'
    [root@shell ~]# sh autossh.sh 192.168.100.130 123456
    spawn ssh 192.168.100.130
    The authenticity of host '192.168.100.130 (192.168.100.130)' can't be established.
    ECDSA key fingerprint is SHA256:urjATAzpLLv0a25Tf02Ibw1bXMiMycqUJOijfkVsLoY.
    ECDSA key fingerprint is MD5:ec:cd:62:72:ee:b6:c1:f7:f6:43:db:3a:04:ad:45:9a.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '192.168.100.130' (ECDSA) to the list of known hosts.
    [email protected]'s password: 
    Last login: Tue Jul 28 01:01:30 2020
    [root@test03 ~]# exit
    登出
    Connection to 192.168.100.130 closed.
    
    
    '正常登陆'
    [root@shell ~]# sh autossh.sh 192.168.100.130 123456
    spawn ssh 192.168.100.130
    root@192.168.100.130's password: 
    Last login: Tue Jul 28 01:03:14 2020 from 192.168.100.120
    [root@test03 ~]# exit
    登出
    Connection to 192.168.100.130 closed.
    

5.3 : FTP免密 登陆

正常流程

[root@ce ~]#ftp 192.168.8.136
Connected to 192. 168.8.136 (192. 168.8.136).
220 (vsFTPd 3.0.2)
Name (192.168.8. 136:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd pub
250 Directory successfully changed.

免密流程

[root@localhost ~]# vim ftp.sh 
#!/usr/bin/expect -f
set timeout 10
spawn ftp 20.0.0.48
expect "Name*"
send "ftp\r"
expect "Password:"
send "\r"
expect "ftp>*"
interact
expect eof

你可能感兴趣的:(Shell编程)