From 4d3b737e2d51a546a262c111b58e7b222efd900b Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 26 Apr 2026 03:23:28 +0800 Subject: [PATCH] =?UTF-8?q?Fix:=20=E4=BD=BF=E7=94=A8=E5=88=86=E9=9A=94?= =?UTF-8?q?=E7=AC=A6=E6=A0=87=E8=AE=B0=E6=8F=90=E5=8F=96=E5=8D=95=E4=B8=AA?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在Shell模式中插入分隔符标记命令边界 - 解决累积输出包含之前命令回显的问题 - display interface等待8秒,lldp等待3秒 --- internal/ssh/client.go | 44 ++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/internal/ssh/client.go b/internal/ssh/client.go index b37cafc..c3da437 100644 --- a/internal/ssh/client.go +++ b/internal/ssh/client.go @@ -182,34 +182,58 @@ func (c *Client) ExecuteCommands(commands []string) ([]string, error) { return nil, fmt.Errorf("failed to start shell: %w", err) } - // 执行命令并收集输出 + // 执行命令并收集输出(使用分隔符标记) results := make([]string, 0, len(commands)) + for i, cmd := range commands { // 等待一段时间防止设备速率限制 if i > 0 { time.Sleep(2 * time.Second) } - // 发送命令(添加换行符) + // 生成分隔符标记命令边界 + delimiter := fmt.Sprintf("===CMD_BOUNDARY_%d===", i) + + // 发送命令 if _, err := stdin.Write([]byte(cmd + "\n")); err != nil { return results, fmt.Errorf("failed to send command '%s': %w", cmd, err) } // 等待命令执行完成(不同命令需要不同等待时间) sleepTime := 1 * time.Second - if cmd == "display interface" { - sleepTime = 5 * time.Second // 大输出命令需要更多时间 + if cmd == "display interface" || strings.Contains(cmd, "display interface") { + sleepTime = 8 * time.Second // 大输出命令需要更多时间 + } else if cmd == "display lldp neighbor-information" { + sleepTime = 3 * time.Second } time.Sleep(sleepTime) + + // 发送分隔符(不执行任何操作,只是标记) + if _, err := stdin.Write([]byte("echo " + delimiter + "\n")); err != nil { + return results, fmt.Errorf("failed to send delimiter: %w", err) + } + + // 等待分隔符输出 + time.Sleep(500 * time.Millisecond) - // 获取当前输出并清理 + // 获取完整输出并清理 rawOutput := stdoutBuf.String() - cleanOutput := cleanCommandOutput(rawOutput, cmd) + + // 找到分隔符位置,提取当前命令的输出部分 + parts := strings.Split(rawOutput, delimiter) + cmdOutput := "" + if len(parts) > 1 { + // 取最后一个分隔符之前的部分(当前命令的输出) + cmdOutput = parts[len(parts)-2] // 倒数第二部分是当前命令输出,最后一部分是分隔符后的空内容 + } else { + cmdOutput = rawOutput + } + + cleanOutput := cleanCommandOutput(cmdOutput, cmd) results = append(results, cleanOutput) - - // 清空缓冲区,为下一个命令做准备(通过位置标记) - stdoutBuf.Reset() - stderrBuf.Reset() + + fmt.Printf("[SSH] Command '%s' extracted %d bytes from %d bytes raw output\n", + cmd, len(cleanOutput), len(rawOutput)) } // 退出shell