shell expect的简单用法

本文介绍了一个简单的Expect脚本,用于实现SSH自动登录过程,并详细解释了脚本每一行的作用及工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自:

http://blog.youkuaiyun.com/zhuying_linux/article/details/6902135


使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄、收藏。可是为什么要这么写却不知其然。本文用一个最短的例子说明脚本的原理。
  脚本代码如下: 
  ############################################## 
  #!/usr/bin/expect 
  set timeout 30 
  spawn ssh -l username 192.168.1.1 
  expect "password:" 
  send "ispass/r" 
  interact 
  ############################################## 
  1. [#!/usr/bin/expect] 
  这一行告诉操作系统脚本里的代码使用那一个shell来执行。这里的expect其实和linux下的bash、windows下的cmd是一类东西。 
  注意:这一行需要在脚本的第一行。 
  2. [set timeout 30] 
  基本上认识英文的都知道这是设置超时时间的,现在你只要记住他的计时单位是:秒 
  3. [spawn ssh -l username 192.168.1.1]
  spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。所以不要用 “which spawn“之类的命令去找spawn命令。好比windows里的dir就是一个内部命令,这个命令由shell自带,你无法找到一个dir.com 或 dir.exe 的可执行文件。
  它主要的功能是给ssh运行进程加个壳,用来传递交互指令。 
  4. [expect "password:"] 
  这里的expect也是expect的一个内部命令,有点晕吧,expect的shell命令和内部命令是一样的,但不是一个功能,习惯就好了。这个命令的意思是判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒
  5. [send "ispass/r"] 
  这里就是执行交互动作,与手工输入密码的动作等效。 
  温馨提示: 命令字符串结尾别忘记加上“/r”,如果出现异常等待的状态可以核查一下。 
  6. [interact] 
  执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行 
  #!/usr/bin/expect   #(注意安装的路径,不确定 whereis expect 一下 )
  # Change a login shell to bash 
  set user [lindex $argv 0] 
  spawn bash $user 
  expect "]:" 
  send "/bin/bash " 
  expect eof 
  exit

例子:

#!/usr/bin/expect -f
set password 123456

set date [exec date -d yesterday "+%Y-%m-%d"]
#exp_internal 1
spawn /usr/bin/scp oracle@192.168.55.232:/home/oracle/cai-website.log.$date /home/oracle/zy/backup/
set timeout 300
expect "password:"
send  "$password\r"
set timeout 300
log_file /home/oracle/zy/test
expect eof

exit

假如该文件名为expect-scp.sh那么就执行

expect expect-scp.sh或者

./expect-scp.sh会得到如下结果:

spawn /usr/bin/scp oracle@192.168.55.232:/home/oracle/cai-website.log.2011-10-24 /home/oracle/zy/backup/
cai-website.log.2011-10-24                                                                        100% 1183KB   1.2MB/s   00:01   
send: spawn id exp6 not open
    while executing

"send  "$password\r""
    (file "expect.sh" line 8)

其实大家可以看出,这个结果还是有问题的,也就是说这个脚本还有那么一点点小问题,各位大仙,如果你要是发现问题了,我们可以一起讨论一下~

<think>我们正在讨论Expect自动化脚本的使用方法。Expect是一个用于自动化交互式应用程序的工具,特别适用于需要输入密码或应答提示的场景。根据引用,我们可以总结Expect的基本使用流程和常用命令。 Expect脚本通常以#!/usr/bin/expect开头,然后使用spawn启动一个交互式进程,接着用expect来匹配进程的输出,根据匹配到的模式发送相应的响应(使用send命令)。最后用expect eof等待进程结束。 常用命令解释: - spawn: 启动一个新的交互式进程。 - expect: 等待进程的特定输出(可以匹配多个模式,并执行不同的响应)。 - send: 向进程发送字符串(包括回车\r)。 - set timeout: 设置等待超时时间(秒),-1表示永不超时。 - interact: 将控制权交给用户(有时在自动化结束后需要人工干预时使用)。 - expect eof: 等待进程结束。 下面我们通过一个示例脚本来具体说明。假设我们需要用ssh登录一台远程服务器,并自动输入密码。 ```expect #!/usr/bin/expect # 设置超时时间,单位秒 set timeout 30 # 启动ssh进程 spawn ssh username@hostname # 匹配可能的输出,并作出响应 expect { # 如果第一次连接,可能会询问是否保存指纹 "yes/no" { send "yes\r" exp_continue # 继续等待下一个模式 } # 提示输入密码 "password:" { send "your_password\r" } } # 等待命令执行结束(这里等待远程命令提示符,然后执行一个命令) expect "$ " # 假设远程提示符是'$ ' send "ls -l\r" # 等待上一条命令执行完成,再次出现提示符 expect "$ " send "exit\r" # 退出远程登录 # 等待spawn启动的进程结束 expect eof ``` 注意:在实际使用中,密码最好不要直接写在脚本里,可以通过参数传递或者从安全的地方获取。 另外,引用[4]中展示了一种在shell脚本中内嵌expect代码的方式,使用`expect -c "..."`。这种方式适合在shell脚本中嵌入简单expect操作。 例如,在shell脚本中嵌入expect实现scp自动上传文件: ```sh #!/bin/sh for item in `cat filelist.txt | grep -v '#'`; do expect -c " set timeout 60 spawn scp $item user@remotehost:/path/ expect { \"*yes/no*\" {send \"yes\r\"; exp_continue} \"*password:\" {send \"your_password\r\"} } expect eof " echo "$item uploaded." done ``` 在这个例子中,我们循环读取文件列表,对每个文件使用expect自动完成scp上传。注意,内嵌的expect脚本需要用双引号括起来,且内部的双引号需要转义。 §§相关问题§§ 1. Expect脚本中如何处理多个可能的提示? 2. 如何安全地在Expect脚本中处理密码? 3. Expect脚本中timeout超时后如何处理? 4. 如何在Shell脚本中嵌入Expect代码? 5. Expect的interact命令有什么作用?</think>### Shell Expect自动化脚本使用方法 Expect是一个用于自动化交互式命令行任务的工具,特别适合处理需要人工输入的密码、确认提示等场景。以下是详细使用方法: #### **1. 基本脚本结构** ```expect #!/usr/bin/expect # 设置超时时间(秒) set timeout 30 # 启动交互式进程 spawn ssh user@hostname # 匹配预期输出并响应 expect { "yes/no" { send "yes\r"; exp_continue } # 处理首次连接提示 "password:" { send "your_password\r" } # 输入密码 } # 等待命令结束 expect eof ``` #### **2. 核心命令详解** - **`spawn`**:启动需交互的进程(如`ssh`, `scp`, `ftp`) - **`expect`**:等待进程输出匹配指定模式 - **`send`**:向进程发送指令(`\r`表示回车) - **`set timeout`**:设置等待响应时间(`-1`为无限等待) - **`exp_continue`**:继续匹配后续模式 - **`interact`**:交还控制权给用户[^2] #### **3. 实战示例** **场景1:自动SCP文件传输** ```expect #!/usr/bin/expect spawn scp file.txt user@remote:/path/ expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "P@ssw0rd!\r" } } expect eof puts "文件传输完成" ``` **场景2:多步交互(如数据库配置)** ```expect spawn mysql_secure_installation expect "Enter password for root:" { send "initial_pwd\r" } expect "New password:" { send "New_Str0ngPwd!\r" } expect "Re-enter new password:" { send "New_Str0ngPwd!\r" } expect "Remove anonymous users?" { send "y\r" } # ... 后续步骤 ``` #### **4. 高级技巧** - **参数化输入**:通过变量传递敏感信息 ```expect set username "admin" set passwd [exec get_password.sh] # 从外部获取密码 ``` - **错误处理**: ```expect expect { "success" { puts "操作成功" } timeout { puts "超时错误"; exit 1 } "denied" { puts "权限错误"; exit 2 } } ``` - **Shell集成**:在Bash中嵌入Expect ```bash #!/bin/bash for ip in $(cat servers.txt); do /usr/bin/expect <<EOF spawn ssh admin@$ip expect "Password:" { send "Admin123\r" } expect "#" { send "uptime\r" } ... EOF done ``` #### **5. 安全建议** 1. 避免在脚本中硬编码密码,使用环境变量或加密存储 2. 设置最小必要权限的账户执行脚本 3. 配合`ssh-key`实现免密登录更安全[^4] > 关键点:Expect的核心是**模式匹配-响应**机制,通过精准预测命令行输出实现自动化交互[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值