如何在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
相关产品推荐
相关产品推荐

