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

通过SSH自动获取控制器诊断文件时Expect脚本致文件损坏的问题排查

看起来你的Expect脚本在处理二进制数据和输出转发时出了问题——tar.gz是二进制文件,而Expect默认的文本模式处理会破坏数据结构,再加上log_user的时机设置导致输出丢失或损坏。咱们来拆解问题并修复它:

原脚本的问题所在

  1. 二进制数据被篡改:Expect原本是为文本交互设计的,当你用expect和log_user捕获输出时,它可能会修改换行符(比如把\r\n转成\n)或者插入意外字符,直接破坏tar.gz的二进制结构。
  2. 输出丢失或延迟:一开始设置log_user 0会屏蔽所有spawn进程的输出,可能在你打开log_user 1之前就错过了tar流的开头部分。即使开启后,Expect的内部处理也会干扰原始二进制流。
  3. EOF处理不可靠:用expect eof等待结束并不能保证拿到完整的二进制流——如果传输时间过长或者输出出现停顿,超时机制可能提前触发,导致文件被截断。

适配二进制输出的修复脚本

这个脚本在认证完成后跳过文本解析,直接把原始二进制流转发到标准输出(这样管道输出到diags.tgz就正常了):

#!/usr/bin/expect -f
# 关闭Expect内部日志,避免污染二进制输出
exp_internal 0
# 设置足够长的超时时间,适配大体积诊断文件
set timeout 300

# 启动SSH命令获取压缩后的诊断文件
spawn ssh diag@controller tarred

# 处理认证流程:匹配密码提示并发送密码
expect {
    "?assword:" {
        send "unrealpassword\r"
        exp_continue
    }
    # 捕获认证失败场景,避免脚本挂起
    "Permission denied" {
        puts stderr "错误:认证失败,请检查密码是否正确"
        exit 1
    }
    # 认证完成后,直接转发原始输出不做任何修改
    -re "\r\n" {
        # -nobuffer 确保无缓冲延迟或文本处理
        interact -nobuffer
    }
}

为什么这个脚本有效

  • exp_internal 0:关闭Expect的调试日志,防止这些日志混入tar.gz文件导致损坏。
  • interact -nobuffer:直接将SSH进程的标准输出无缓冲地转发到脚本的标准输出,完全保留tar.gz的原始二进制结构。
  • 错误处理:expect块会捕获认证失败的情况,让你得到明确的错误提示,而不是拿到一个不完整的损坏文件。

额外建议

  • 先不管道到文件,直接运行脚本测试认证是否正常:./get_diags.exp会输出一堆乱码(这是tar.gz二进制的正常表现),说明数据流没问题。
  • 如果还是出现超时,增大set timeout的值——有些诊断文件体积较大,传输需要更长时间。

内容的提问来源于stack exchange,提问作者G. Ryvia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:35:05