Golang获取HP路由器远程命令输出的方法

Golang获取HP路由器远程命令输出的方法 我的任务是在不同的路由器上执行命令。

我使用的是 golang.org/x/crypto/ssh 包。

思科路由器工作正常。但在惠普路由器上,输出在命令实际执行前就结束了。 以下是代码示例:

 cmd := "dis int brief"
 config := &ssh.ClientConfig{
   User: user,
   Auth: []ssh.AuthMethod{
      ssh.Password(password),
   },
   ...
}
...
conn, err := ssh.Dial("tcp", hostip+":22", config)
session, err := conn.NewSession()
output, err := session.CombinedOutput(cmd)

在输出中,我只得到了实际命令之前的文本,就像它是前一个命令的缓冲区,但我也没有收到任何错误。

有人知道惠普路由器的问题是什么吗?


更多关于Golang获取HP路由器远程命令输出的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang获取HP路由器远程命令输出的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这个问题通常与HP网络设备(如Comware系统)的SSH实现方式有关。HP设备在SSH会话中执行命令时,可能需要显式地发送终端类型并处理提示符。

以下是修改后的代码示例,添加了伪终端(PTY)配置:

package main

import (
    "fmt"
    "golang.org/x/crypto/ssh"
    "log"
)

func executeHPCommand(hostip, user, password, cmd string) (string, error) {
    config := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }

    conn, err := ssh.Dial("tcp", hostip+":22", config)
    if err != nil {
        return "", err
    }
    defer conn.Close()

    session, err := conn.NewSession()
    if err != nil {
        return "", err
    }
    defer session.Close()

    // 为HP路由器设置伪终端
    modes := ssh.TerminalModes{
        ssh.ECHO:          0,     // 禁用回显
        ssh.TTY_OP_ISPEED: 14400, // 输入速度
        ssh.TTY_OP_OSPEED: 14400, // 输出速度
    }

    // 请求PTY,指定终端类型
    if err := session.RequestPty("vt100", 80, 40, modes); err != nil {
        return "", err
    }

    // 执行命令并获取输出
    output, err := session.CombinedOutput(cmd)
    if err != nil {
        return "", err
    }

    return string(output), nil
}

func main() {
    output, err := executeHPCommand("192.168.1.1", "admin", "password", "dis int brief")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(output)
}

如果问题仍然存在,可以尝试使用交互式会话的方式:

func executeHPCommandInteractive(hostip, user, password, cmd string) (string, error) {
    config := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }

    conn, err := ssh.Dial("tcp", hostip+":22", config)
    if err != nil {
        return "", err
    }
    defer conn.Close()

    session, err := conn.NewSession()
    if err != nil {
        return "", err
    }
    defer session.Close()

    // 获取输入输出管道
    stdin, err := session.StdinPipe()
    if err != nil {
        return "", err
    }
    
    stdout, err := session.StdoutPipe()
    if err != nil {
        return "", err
    }

    // 设置伪终端
    modes := ssh.TerminalModes{
        ssh.ECHO:          0,
        ssh.TTY_OP_ISPEED: 14400,
        ssh.TTY_OP_OSPEED: 14400,
    }

    if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
        return "", err
    }

    // 启动shell
    if err := session.Shell(); err != nil {
        return "", err
    }

    // 发送命令
    _, err = fmt.Fprintf(stdin, "%s\n", cmd)
    if err != nil {
        return "", err
    }

    // 读取输出
    buf := make([]byte, 4096)
    n, err := stdout.Read(buf)
    if err != nil {
        return "", err
    }

    // 发送退出命令
    fmt.Fprintf(stdin, "quit\n")

    return string(buf[:n]), nil
}

对于HP路由器,还可以尝试在命令后添加换行符和等待时间:

// 在原有代码基础上修改命令执行部分
cmd := "dis int brief\n"
output, err := session.CombinedOutput(cmd)

// 或者使用带超时的执行
import "time"

func executeWithTimeout(session *ssh.Session, cmd string, timeout time.Duration) (string, error) {
    done := make(chan error, 1)
    var output []byte
    var err error
    
    go func() {
        output, err = session.CombinedOutput(cmd)
        done <- err
    }()
    
    select {
    case <-time.After(timeout):
        return "", fmt.Errorf("command timed out")
    case err := <-done:
        if err != nil {
            return "", err
        }
        return string(output), nil
    }
}

这些修改应该能解决HP路由器上命令输出不完整的问题。关键点在于正确配置PTY和终端类型,以及处理设备特定的SSH实现差异。

回到顶部