如何在expect脚本中获取spawn启动的scp进程返回码
expect获取spawn启动的scp进程返回码实现方案
核心原理:expect中spawn拉起的子进程退出状态,需要通过wait命令捕获后提取,你原有脚本存在几处语法、逻辑问题会导致拿不到返回码,需要一并修正:
- 关键字大小写错误:expect内置命令
spawn/expect均为小写,原脚本大写开头的Spawn/Expect会直接执行报错;另外bash中定义的密码变量是Password,后续引用写为$password大小写不匹配,会读不到密码值 - 引号嵌套错误:原脚本在bash双引号包裹的expect代码内,直接使用双引号写匹配规则
"*password:*",会被bash提前截断字符串,导致expect语法解析失败 - 逻辑缺失:发送密码后使用
interact会直接将控制台控制权交还给用户,不会自动等待scp执行完成,也没有配置进程状态捕获逻辑 - shebang写法错误:脚本开头解释器路径少了
!,正确写法为#!/bin/bash
修正后可直接运行的脚本
#!/bin/bash Password=1234 expect -c " # 关闭超时限制,避免大文件传输中途被expect默认超时机制中断 set timeout -1 spawn /usr/bin/scp -r /tmp/ss sus@servername:/var/tmp/ expect { \"*password:*\" { send \"$Password\r\" # 等待scp传输完成、连接断开,不要使用interact expect eof } eof { # 已配置免密登录时不会弹出密码提示,直接等待进程结束 } } # 回收子进程资源,wait返回格式为 {pid spawn_id 退出类型 退出码} set wait_result [wait] set scp_exit_code [lindex \$wait_result 3] # 将scp的退出码作为expect进程的退出码返回给外层bash exit \$scp_exit_code " # 外层bash通过$?即可拿到scp的真实执行返回码 echo "scp执行返回码: $?"
关键说明
- 返回码规则和scp原生规则完全一致:返回0代表传输成功,非0代表执行失败(常见原因包括认证失败、文件不存在、权限不足、网络中断、目标路径不可写等)
- 提取返回码时取
wait返回列表的第4个元素(tcl列表索引从0开始,所以索引值为3),该值就是spawn拉起的scp进程的真实退出码 - 如果需要排查匹配问题,可以在expect代码开头加
exp_internal 1开启调试日志,能看到完整的交互匹配、进程状态流转过程
内容的提问来源于stack exchange,提问作者sirisha
相关产品推荐
相关产品推荐

