Shell Expect 命令

2023-11-09

expect可以实现shell实现不了的用户交互的需求。expect可以将交互写在一个脚本上,完成很多自动化的动作,比如ssh、ftp登陆等,都是需要交互需求的。expect是需要安装的,直接yum  -y install expect安装即可。

expect的四个关键命令为:spawn、expect、send、set,其中spawn是调用要执行的命令,expect是等待命令提示信息的出现也即捕捉用户提示信息,send是发送需要交互的信息来替代手工的输入,set则是输入变量值。

一、expect关键语法

1、关键语法

[#!/usr/bin/expect] 这一行告诉操作系统脚本里的代码使用那一个shell来执行。这里的expect其实和linux下的bash、windows下的cmd是一类东西。 注意:这一行需要在脚本的第一行。

spawn              调用要执行的命令
expect               只有spawn执行的命令的执行结果才被expect捕捉到,主要包括标准输入的提示信息、eof和timeout。等待命令提示信息的出现,也就是捕捉用户输入的提示:
send                 发送需要交互的值,替代了用户手动输入内容
set                    设置变量值
interact             执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
expect eof        这个一定要加,与spawn对应表示捕获终端输出信息终止,类似于if....endif

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

2、常见设置

set timeout -1      设置expect永不超时  

set timeout 300   设置expect 300秒超时,如果超过300没有expect内容出现,则退出    

PS:为什么要设置超时时间,因为默认时间是10s,则在交互执行的过程中,很可能会断开,导致任务执行没完成就终止。我司的一个从远程ftp上同步文件的计划任务总是执行终止,后来设置了超时时间为-1就可以了。

二、expect的用法示例

1、一个简单的拉取文件的例子

    #!/usr/bin/expect -f
    set passwd "123456"     ##这个是你设置的密码
    set timeout -1          ##设置超时时间
    spawn sftp -P 2022 Jmsftp@ftp.jms.com
     
    expect "password:"
    send "$passwd\r"
    expect "sftp>"
    send "get -r data/201711*\r"
    expect "sftp>"
    send "exit\r"
    interact

2、一个小例子,用于linux下账户的建立:

    1 #!/usr/bin/expect
      2
      3 set passwd "mypasswd"    
      4 set timeout 60           
      5
      6 if {$argc != 1} {
      7     send "usage ./account.sh \$newaccount\n"
      8     exit
      9 }
     10
     11 set user [lindex $argv [expr $argc-1]]
     12
     13 spawn sudo useradd -s /bin/bash -g mygroup -m $user
     14
     15 expect {
     16     "assword" {
     17         send_user "sudo now\n"
     18         send "$passwd\n"
     19         exp_continue
     20     }
     21     eof
     22     {
     23         send_user "eof\n"
     24     }
     25 }
     26
     27 spawn sudo passwd $user
     28 expect {
     29     "assword" {
     30         send "$passwd\n"
     31         exp_continue
     32     }
     33     eof
     34     {
     35         send_user "eof"
     36     }
     37 }
     38
     39 spawn sudo smbpasswd -a $user
     40 expect {
     41     "assword" {
     42         send "$passwd\n"
     43         exp_continue
     44     }
     45     eof
     46     {
     47         send_user "eof"
     48     }
     49 }
     

以上脚本的注意点如下:
第3行: 对变量赋值的方法;
第4行: 默认情况下,timeout是10秒;
第6行: 参数的数目可以用$argc得到;
第11行:参数存在$argv当中,比如取第一个参数就是[lindex $argv 0];并且如果需要计算的话必须用expr,如计算2-1,则必须用[expr 2-1];
第13行:用spawn来执行一条shell命令,shell命令根据具体情况可自行调整;有文章说sudo要加-S,经过实际测试,无需加-S亦可;
第15行:一般情况下,如果连续做两个expect,那么实际上是串行执行的,用例子中的结构则是并行执行的,主要是看匹配到了哪一个;在这个例子中,如果你写成串行的话,即
expect "assword"
send "$passwd\n"
expect eof
send_user "eof"
那么第一次将会正确运行,因为第一次sudo时需要密码;但是第二次运行时由于密码已经输过(默认情况下sudo密码再次输入时间为5分钟),则不会提示用户去输入,所以第一个expect将无法匹配到assword,而且必须注意的是如果是spawn命令出现交互式提问的但是expect匹配不上的话,那么程序会按照timeout的设置进行等待;可是如果spawn直接发出了eof也就是本例的情况,那么expect "assword"将不会等待,而直接去执行expect eof。
这时就会报expect: spawn id exp6 not open,因为没有spawn在执行,后面的expect脚本也将会因为这个原因而不再执行;所以对于类似sudo这种命令分支不定的情况,最好是使用并行的方式进行处理;
第17行:仅仅是一个用户提示而已,可以删除;
第18行:向spawn进程发送password;
第19行:使得spawn进程在匹配到一个后再去匹配接下来的交互提示;
第21行:eof是必须去匹配的,在spawn进程结束后会向expect发送eof;如果不去匹配,有时也能运行,比如sleep多少秒后再去spawn下一个命令,但是不要依赖这种行为,很有可能今天还可以,明天就不能用了;

3、下面这个例子比较特殊,在整个过程中就不能expect eof了

    1  #!/usr/bin/expect
     2   set mypassword=123456
     3  set timeout 30
     4  spawn ssh 10.192.224.224
     5  expect "password:"
     6  send "mypassword\n"
     7  expect "*$"
     8  send "mkdir tmpdir\n"
     9  expect "*$"

这个例子实际上是通过ssh去登录远程机器,并且在远程机器上创佳一个目录,我们看到在我们输入密码后并没有去expect eof,这是因为ssh这个spawn并没有结束,而且手动操作时ssh实际上也不会自己结束除非你exit;所以你只能expect bash的提示符,当然也可以是机器名等,这样才可以在远程创建一个目录。注意,请不要用spawn mkdir tmpdir,这样会使得上一个spawn即ssh结束,那么你的tmpdir将在本机建立。当然实际情况下可能会要你确认ssh key,可以通过并行的expect进行处理,不多赘述。


PS:在shell脚本中插入expect命令,格式为如下


    #!/bin/sh
    expect <<!    ##开头
    spawn ssh xx@yyy
    expect "*Password*"
    send "xxx\r"
    expect ">"
    send "mkdir xxxxx\r"
    send "exit\r"
    expect eof
    !          ##结尾

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Shell Expect 命令 的相关文章

  • 进程如何知道它已收到信号

    如果我错了 请纠正我 以下是我对信号的理解 据我所知 信号生成 和信号传递有2个不同 事物 为了产生信号 操作系统只是在位数组中设置一个位 在过程控制中维护 工艺块 PCB 每一位 对应于特定信号 当设置一个位时 这意味着 该位对应的信号为
  • 删除 Python 中某些操作的 root 权限

    在我的 Python 脚本中 我执行了一些需要 root 权限的操作 我还创建并写入文件 我不想由 root 独占所有 而是由运行我的脚本的用户独占所有 通常 我使用以下命令运行脚本sudo 有办法做到上述吗 您可以使用以下方式在 uid
  • X 按键/释放事件捕获,与焦点窗口无关

    我想记录所有传入的按键事件 无论哪个窗口处于焦点状态或指针位于何处 我编写了一个示例代码 它应该捕获当前焦点窗口的按键事件 include
  • 在Linux中创建可执行文件

    我计划做的一件事是编写 非常简单的 Perl 脚本 并且我希望能够在不从终端显式调用 Perl 的情况下运行它们 我明白 要做到这一点 我需要授予他们执行权限 使用 chmod 执行此操作非常简单 但它似乎也是一个稍微费力的额外步骤 我想要
  • php56 - CentOS - Remi 仓库

    我刚刚在测试盒上安装了 php 5 6 正常的 cli php 解释器似乎不存在 gt php v bash php command not found gt php56 v PHP 5 6 13 cli built Sep 3 2015
  • %config(noreplace) 文件上出现意外的 RPM 冲突

    我正在创建我自己的RPM using rpmbuild My RPM 包含配置文件哪个应该永远不会被覆盖 即使 RPM 包含这些配置文件的新版本 为了存档这个 我用以下标签标记了它们 config noreplace opt mypacka
  • 为什么“script”命令会生成 ^[ 和 ^M 字符以及如何使用 vim 搜索和替换删除它们?

    在linux上 使用bash shell 当我使用script命令时 生成的文件称为typescript 当我用 vim 打开该文件时 每一行都包含 M字符 并且有几行 由于我的彩色命令提示符 包含一个字符 我想用任何东西替换这些字符 从而
  • 如何获取 bash 中从 Ping 接收到的数据包的百分比?

    当 ping 主机时 我希望输出仅显示收到的数据包 已发送 5 个 的百分比 我想我需要使用grep不知怎的 但我不知道如何 我是 bash 编程的新手 这是我所在的地方 ping c 5 q host grep grep 中应该包含什么
  • Laravel 内存问题?

    各位 我在 DO 服务器上遇到这样的问题 我已经尝试了一切 整个网站在使用 Homestead 的 Linux 服务器上 100 正常工作 但上传后 它只能工作一次 在重新加载或刷新页面后会多次下降 我尝试增加 apache 服务器的内存
  • 如何在 Linux 中显示进程状态(阻塞、非阻塞)

    有没有办法查询 Linux 进程表中进程的状态 以便能够演示执行查询时进程是正在运行还是被阻止 我的目标是从进程或程序的 外部 执行此操作 因为我希望从操作系统进程的角度来理解这一点 但欢迎任何想法 这是Python代码阻塞的过程 impo
  • 如何在树莓派上更新到最新的 python 3.5.1 版本?

    我昨天拿到了 Raspberry Pi 我已经在尝试用它来编写代码了 我有一个计划在其上运行的程序 但它仅与 Python 版本 3 5 0 或 3 5 1 兼容 并且我在互联网上找到的所有内容似乎都已经过时 与 Python 2 有关 或
  • Docker 容器可以访问 DNS,但无法解析主机

    我在运行 docker 容器时遇到一个有趣的问题 突然间 我无法从容器内解析 DNS 这是一个概要 一切都没有解决 apt get pip 一次性 ping 容器等正在运行docker run it dns 8 8 8 8 ubuntu p
  • CMake:使用其他平台的生成器。如何?

    如何使用 CMake 在 Linux 上生成 Visual Studio 项目文件 你不能 您必须在 Windows 上运行 CMake 才能为 Visual Studio 生成
  • 如何从 Linux 命令行打开 Sublime Text 2 文件到选项卡,而不是新窗口

    我有 ST2 设置 这样我就可以执行 sublime file txt 它将在 ST2 窗口中打开 但是我怎样才能让它在当前打开的窗口的新选项卡中打开呢 尝试 Sublime 命令行帮助 subl 帮助 Sublime Text 2 内部版
  • 如何使用 shell 脚本解压所有 .tar.gz?

    我试过这个 DIR path tar gz if ls A DIR 2 gt dev null then echo not gz else tar zxvf path tar gz C path tar fi 如果该文件夹有一个 tar 则
  • 如何获取文件夹的大小,包括稀疏文件的表观大小? (du太慢了)

    我有一个包含很多KVM qcow2文件的文件夹 它们都是稀疏文件 现在我需要获取文件夹的总大小 qcow2 文件大小应计为表观大小 而不是实际大小 例如 图片 c9f38caf104b4d338cc1bbdd640dca89 qcow2 文
  • 如何从powershell获取主机名?

    我如何获得hostname https stackoverflow com q 42014215 262852 for dur来自 powershell PS home thufir powershell gt PS home thufir
  • gnutls_handshake() 失败:握手失败 GIT

    一切都工作正常 但突然我收到错误 致命 无法访问 https 电子邮件受保护 cdn cgi l email protection name repo name git gnutls handshake 失败 握手失败 我在我的计算机和 E
  • 如何搭建qtwayland?

    我花了一整天的时间尝试使用QtWayland Compositor 1 0在 Qt 创建者中 我已经遵循了从那里开始的所有步骤https wiki qt io QtWayland https wiki qt io QtWayland但我收到
  • 打破条件变量死锁

    我遇到这样的情况 线程 1 正在等待条件变量 A 该变量应该由线程 2 唤醒 现在线程 2 正在等待条件变量 B 该变量应该由线程 1 唤醒 在我使用的场景中条件变量 我无法避免这样的死锁情况 我检测到循环 死锁 并终止死锁参与者的线程之一

随机推荐

  • GIT操作:把当前仓库的一个分支push到另一个仓库的指定分支

    背景 有时候我们想把当前仓库A的一个指定分支1 推给 另一个仓库B的另一个指定分支2 可以通过2个主要命令git remote xxx 和 git push newOrigin 当前分支 目标分支 完成 示例 假设有2个仓库uu和uunew
  • java什么时候需要用序列化?

    文章目录 一 Java序列化概述 二 什么时候用序列化 三 项目创建很多对象怎么优化 场景 优化思路一 加条件判断 优化思路二 使用clone浅拷贝 一 Java序列化概述 简单说就是为了保存在内存中的各种对象的状态 也就是实例变量 不是方
  • vscode 缩进,取消自动格式化,溢出不换行

    Ctrl P gt 在输入框中输入 settings json 打开第一个 取消自动换行 editor wordWrap off 代码缩进 editor tabSize 4 取消每次保存的时候自动格式化 editor formatOnSav
  • 离散数学:常用的数学符号

    x A x 是 A 的元素 x A x 不是 A 的元素 A B A 是 B 的子集 或 A 包含于 B B 包含 A A B A 是 B 的真子集 A B B 不包含 A 或 A 不包含 B A B A 与 B 有相同的元素 A B A
  • zookeeper的Linux下安装和使用 单机版/集群版

    这个是单节点的 集群的在另一篇文章里做了说明 一 解压zookeeper的tar包 二 到zookeeper的conf目录下 拷贝zoo sample cfg 为zoo cfg 记住名字必须叫zoo cfg root VM 0 7 cent
  • 【高级篇 / SDWAN】(7.0) ❀ 07. DNS 解析最快的宽带优先上网 ❀ FortiGate 防火墙

    自从配置SD WAN之后 很多人反应网速变慢了 打开网站卡半天 你有没有接到过这种投诉 其实这是因为DNS解析的原因 由于多条宽带属于不同的运营商 而运营商自带的DNS对自己宽带的解析很快 但对其它宽带就会报错 所以我们只能使用通用DNS
  • 2021-08-06

    在编译OKVIS中 执行make j8时报错的解决方法 1 根据github上OKVIS的安装步骤一步一步执行 由于github经常进不去 我就进了gitee网站查到OKVIS的安装步骤 参考链接 https gitee com bill4
  • vue 引入 二维码

    vue cli3 动态生成二维码 不带logo的 第一步 先下载插件 npm install qrcodejs2 save 第二步 在需要生成二维码的 页面 导入 import QRCode from qrcodejs2 第三步 在页面中引
  • [云原生专题-34]:K8S - 核心概念 - 网络 - Web服务器与反向代理服务器nginx入门介绍

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 122806880 目录 第1章 常见网
  • 深入了解一下C语言scanf()库函数

    目录 一 scanf函数的定义 二 scanf函数的返回值 三 scanf函数的控制符 四 scanf函数控制符的使用 1 一般用法 2 scanf 函数 控制符的用法 2 1 控制符的两种形式 2 2 字符的使用 3 键盘缓冲区残余信息问
  • Confluence 6 管理应用服务器内存设置

    应用服务器中的最小和最大 JVM Heap 空间配置将会影响系统的性能 Confluence 管理员可能希望对默认的配置进行修改 基于你系统的负载不同配置情况也会有所不同 请参考页面 Server Hardware Requirements
  • sed命令常见用法

    常见sed命令的操作 a 增加 在当前行下面增加一行指定内容 c 整行替换 将选定行替换为指定内容 d 删除 删除选定的行 w 将行写入新文件 r 从文件中读取 i 插入 在选定行上面插入一行指定内容 p 打印 如果同时指定行 表示打印指定
  • 五彩斑斓的黑

  • c++操作sqllite

    项目中需要使用的sqllite 有想过使用内存的结果 好像都不大使用 最接近的算是vector了 但是查询方式不大好 而且数据有好几个字段 所以考虑了数据库 sqllite目前已经到了3了 好快 好像这个数据库也不弱 就先用着吧 其实挺简单
  • FPGA—串口RS232(附实现代码)

    目录 1 理论 1 1 串口简介 1 2 RS232信号线 1 3 RS232通信协议简介 2 实操 2 1 硬件资源 2 2 顶层模块 2 2 1 模块说明 2 2 2 RTL 代码 2 2 3 仿真验证 2 3 串口数据接收模块 2 3
  • PyCharm集成SVN,检出、提交代码

    工作需要 使用PyCharm集成SVN 进行代码管理 搜索网上资料 没有讲的很清楚的 自己动手摸索 大致了解了使用方法 遂记录下来 希望他人少走些弯路
  • 比较Opencv自带的frontface检测器

    CascadeClassifier haarcascade frontalface alt new CascadeClassifier xml haarcascade frontalface alt xml CascadeClassifie
  • 【Linux】Linux服务器解决python3.7与openssl的低版本不兼容的问题

    安装了Python3 7之后 遇到的一个很麻烦的坑就是与系统自带的ssl版本不兼容 Python3 7需要的openssl的版本为1 0 2或者1 1 x 这个requirements在config Python3 7的时候使用 with
  • c++栈实现表达式求值

    文章目录 前言 一 思想分析 二 具体实现 前言 后缀表达式的算法思想与具体实现 一 思想分析 设定两个栈 操作数栈 OPND 操作符栈 OPTR 栈初始化 置操作数栈 OPND 为空 操作符栈 OPTR 中预设一个优先级最低的操作符 自左
  • Shell Expect 命令

    expect可以实现shell实现不了的用户交互的需求 expect可以将交互写在一个脚本上 完成很多自动化的动作 比如ssh ftp登陆等 都是需要交互需求的 expect是需要安装的 直接yum y install expect安装即可