You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expect 5.45脚本:如何获取send命令的远程执行返回值

解决Expect脚本远程执行命令只返回纯净结果的问题

我太懂你的困扰了——写的Expect远程脚本总是输出一堆乱七八糟的交互信息,而你只想拿到命令执行的干净结果对吧?咱们直接动手改脚本,把冗余信息全部过滤掉。

原脚本的核心问题

你的脚本现在用interact把终端控制权交还给用户,而且没有对ssh登录欢迎信息、输入的命令本身、提示符这些内容做过滤。要拿到纯净的命令输出,我们需要调整这几个关键环节:

  • 关闭默认的全局交互日志,避免打印所有会话过程
  • 精准匹配远程服务器的提示符,防止误捕获无关内容
  • 专门捕获命令执行后的输出,剥离冗余部分
  • 用正常的会话结束逻辑替换interact

修改后的完整脚本

#!/usr/bin/expect
#usage: no_interact_cmd.sh ip_address username password command
set ip_address [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set command [lindex $argv 3]

# 关闭默认交互日志,只保留我们主动捕获的内容
log_user 0

spawn ssh ${username}@${ip_address}
expect {
    "*password:" {
        send "${password}\n"
    }
    # 处理首次连接的主机密钥确认(可选,根据你的场景调整)
    "*Are you sure you want to continue connecting (yes/no)?" {
        send "yes\n"
        expect "*password:"
        send "${password}\n"
    }
}

# 匹配登录后的提示符:兼容root的#和普通用户的$,可根据实际格式调整
expect -re {\$|#}

# 发送要执行的命令
send "${command}\n"

# 捕获命令执行结果:匹配从命令输出结束到下一个提示符之间的内容
expect -re "(.*)\n(\$|#)"
set clean_output $expect_out(1,string)

# 退出远程会话
send "exit\n"
expect eof

# 打印最终的纯净结果
puts $clean_output

关键修改点说明

  1. log_user 0:直接关闭Expect默认的全量交互日志输出,避免打印spawn、send、expect的所有过程信息。
  2. 灵活的提示符匹配:用正则-re {\$|#}适配大部分服务器的提示符(root用#,普通用户用$),如果你的服务器提示符是[user@host ~]#这种格式,可以改成-re "\[.*\] (\$|#)"。
  3. 精准捕获输出:通过expect -re "(.*)\n(\$|#)"把命令执行后到下一个提示符前的所有内容存到clean_output变量里,这就是我们要的纯净结果。
  4. 替换interact为expect eof:interact会把终端控制权交回用户,而expect eof会等待ssh会话正常结束,避免脚本提前退出。
  5. 新增主机密钥处理:首次连接新服务器时会弹出密钥确认提示,脚本里加了这个分支,防止脚本卡住。

测试执行

用你原来的命令测试:

./no_interact_cmd.sh 192.?.?.? root *** 'hostname'

现在应该只会输出目标主机的hostname,再也看不到那些冗余的交互信息了。

额外提示

如果你的命令执行时间较长,可以给expect加上超时参数,比如expect -timeout 30 -re "(.*)\n(\$|#)",避免脚本无限等待。

内容的提问来源于stack exchange,提问作者liuchu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:58:48