Go 发送SSH命令以配置网络设备

Go 发送SSH命令以配置网络设备,go,ssh,network-programming,Go,Ssh,Network Programming,我正在编写一个CLI,用于在Go 1.9.2中通过SSH通过Cisco无线控制器配置Cisco接入点。我正在使用golang.org/x/crypto/ssh包处理与无线控制器的连接。我能够成功地通过SSH连接到所需的控制器,但在尝试向控制器发送命令时遇到了问题。我知道问题是由于控制器的提示和输出到标准输出。手动连接到控制器时,这是输出: $ ssh <controller_ip> (Cisco Controller) User: username Password:******

我正在编写一个CLI,用于在Go 1.9.2中通过SSH通过Cisco无线控制器配置Cisco接入点。我正在使用golang.org/x/crypto/ssh包处理与无线控制器的连接。我能够成功地通过SSH连接到所需的控制器,但在尝试向控制器发送命令时遇到了问题。我知道问题是由于控制器的提示和输出到标准输出。手动连接到控制器时,这是输出:

$ ssh <controller_ip>


(Cisco Controller)
User: username
Password:****************
(Cisco Controller) >
我知道这是因为控制器希望传递用户名

那么,我的问题是,如何正确处理解析输出并向控制器发送命令?一般来说,我是网络编程新手,所以非常感谢您的帮助。以下是我到目前为止的完整代码:

const (
    HOST = "hostname"
)

func main() {
    hostKey, err := HostKeyCheck(HOST)
    if err != nil {
        log.Fatal(err)
    }

    key, err := ioutil.ReadFile("/Users/user/.ssh/id_rsa")
    if err != nil {
        log.Fatalf("unable to read private key: %v", err)
    }

    // Create the Signer for this private key.
    signer, err := ssh.ParsePrivateKey(key)
    if err != nil {
        log.Fatalf("unable to parse private key: %v", err)
    }

    // Create client config
    config := &ssh.ClientConfig{
        User: "username",
        Auth: []ssh.AuthMethod{
            ssh.Password("password"),
            // Use the PublicKeys method for remote authentication.
            ssh.PublicKeys(signer),
        },
        HostKeyCallback: ssh.FixedHostKey(hostKey),
        Timeout: time.Second * 5,
    }

    // Connect to the remote server and perform the SSH handshake.
    client, err := ssh.Dial("tcp", HOST+":22", config)
    if err != nil {
        log.Fatalf("unable to connect: %v", err)
    }
    defer client.Close()
    // Create a session
    session, err := client.NewSession()
    if err != nil {
        log.Fatal("Failed to create session: ", err)
    }
    defer session.Close()

    // Error occurs after this point
    var b bytes.Buffer
    session.Stdout = &b
    if err := session.Run("show"); err != nil {
        log.Fatalf("%v", err)
    }
    fmt.Println(b.String())        
}

func HostKeyCheck(host string) (ssh.PublicKey, error) {
    file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
    if err != nil {
        return nil, err
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    var hostKey ssh.PublicKey
    for scanner.Scan() {
        fields := strings.Split(scanner.Text(), " ")
        if len(fields) != 3 {
            continue
        }
        if strings.Contains(fields[0], host) {
            hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
            if err != nil {
                return nil, errors.New(fmt.Sprintf("error parsing %q: %v", fields[2], err))
            }
            break
        }
    }

    if hostKey == nil {
        return nil, errors.New(fmt.Sprintf("no hostkey for %s", host))
    }

    return hostKey, nil
}
这是我在运行程序时得到的输出:

$ go run main.go
2017/12/28 14:13:28 ssh: command show failed
exit status 1
以下是一个例子:

您不需要启动新会话来启动命令吗

希望能有帮助

func connectToHost(user, host string) (*ssh.Client, *ssh.Session, error) {
    var pass string
    fmt.Print("Password: ")
    fmt.Scanf("%s\n", &pass)

    sshConfig := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{ssh.Password(pass)},
    }

    sshConfig.HostKeyCallback = ssh.InsecureIgnoreHostKey()

    client, err := ssh.Dial("tcp", host, sshConfig)
    if err != nil {
        return nil, nil, err
    }

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

    return client, session, nil
}

你到底想干什么?您想要一个交互式会话吗?您是否正在尝试像“expect”那样自动化交互式会话?您想发送要执行的完整命令吗?@JimB我想发送多条完整命令您没有按原样发送任何命令。从@JimB开始,我已经做到了。无论我传递什么命令来运行,该命令都会出现SSH错误。您发送了什么?错误是什么?
func connectToHost(user, host string) (*ssh.Client, *ssh.Session, error) {
    var pass string
    fmt.Print("Password: ")
    fmt.Scanf("%s\n", &pass)

    sshConfig := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{ssh.Password(pass)},
    }

    sshConfig.HostKeyCallback = ssh.InsecureIgnoreHostKey()

    client, err := ssh.Dial("tcp", host, sshConfig)
    if err != nil {
        return nil, nil, err
    }

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

    return client, session, nil
}