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

如何在Expect脚本的SSH root会话中获取命令退出状态

如何在Expect脚本中捕获root用户执行命令的退出状态

你的问题核心在于切换到root用户后,提示符匹配错了——普通用户的提示符是$,但root的默认提示符是#,原来的代码里还是用expect -re {\$ $}去匹配,导致后续命令的输出没被正确捕获,expect_out(buffer)自然就只保留了之前切换root的残留内容。

下面是调整后的完整代码,我标注了关键修改点:

spawn ssh $TARGET_USER@$TARGET_IP
expect {
    "yes/no" { 
        send "yes\r"
        expect "*?assword" { send "$TARGET_PASS\r" }
    }
    "*?assword" { send "$TARGET_PASS\r" }
}
# 匹配普通用户的提示符
expect -re {\$ $}

# 切换到root用户
send "su - root\r"
expect { "Password: " { send "$TARGET_PASS\r" } }
# 关键:匹配root的提示符(#),而非普通用户的$
expect -re {# $}

# 在root权限下执行目标脚本
send "sh /home/$TARGET_USER/xxx.sh\r"
# 等待脚本执行完成,匹配root提示符
expect -re {# $}

# 获取上一条命令的退出状态
send "echo \$\?\r"
# 再次等待root提示符,确保输出完全返回
expect -re {# $}

# 捕获输出内容
set output $expect_out(buffer)
puts "------> $output <-------\n"

# 依次退出root和普通用户会话
send "exit\r"
expect -re {\$ $}
send "exit\r"
expect eof

关键修改说明:

  • 切换到root后,所有后续的expect操作都要匹配root的提示符#,这样Expect才能正确识别命令执行完毕的时机,确保捕获到完整的输出。
  • 执行完脚本和echo $?后,必须等待root提示符出现再去读取expect_out(buffer),避免因输出未完全返回导致的内容缺失。

如果想更精准地提取退出状态值(而非整个buffer内容),可以用正则匹配直接捕获数字:

send "echo \$\?\r"
# 用正则匹配直接捕获退出状态的数字值
expect -re {(\d+)\s*# $}
set exit_status $expect_out(1,string)
puts "目标脚本的退出状态是:$exit_status"

这样就能直接拿到你需要的退出状态变量,无需处理冗余的输出内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:00:06