使用golang crypto / ssh在Cisco上运行多个命令

I have the following code pieced together that will let me send read and write to the ssh console of a Cisco box but I am currently not sure how to send multiple commands in the same session.

I am including the entire program in order to server as a starting point for others attempting the same thing in the future, I could not find a working example specifically for Golang<->Cisco.

package main

import (
    "fmt"
    "io"
    "io/ioutil"
    "net"
    "os"
    //"strings"

    "golang.org/x/crypto/ssh"
    "golang.org/x/crypto/ssh/agent"
)

type SSHCommand struct {
    Stdin  io.Reader
    Stdout io.Writer
    Stderr io.Writer
}

type SSHClient struct {
    Config *ssh.ClientConfig
    Host   string
    Port   int
}

func (client *SSHClient) RunCommand(cmd *SSHCommand) error {
    var (
        session *ssh.Session
        err     error
    )

    if session, err = client.newSession(); err != nil {
        return err
    }
    defer session.Close()

    if err = client.prepareCommand(session, cmd); err != nil {
        return err
    }

    err = session.Run("en")


    return err
}

func (client *SSHClient) prepareCommand(session *ssh.Session, cmd *SSHCommand) error {

    if cmd.Stdin != nil {
        stdin, err := session.StdinPipe()
        if err != nil {
            return fmt.Errorf("Unable to setup stdin for session: %v", err)
        }
        go io.Copy(stdin, cmd.Stdin)
    }

    if cmd.Stdout != nil {
        stdout, err := session.StdoutPipe()
        if err != nil {
            return fmt.Errorf("Unable to setup stdout for session: %v", err)
        }
        go io.Copy(cmd.Stdout, stdout)
    }

    if cmd.Stderr != nil {
        stderr, err := session.StderrPipe()
        if err != nil {
            return fmt.Errorf("Unable to setup stderr for session: %v", err)
        }
        go io.Copy(cmd.Stderr, stderr)
    }

    return nil
}

func (client *SSHClient) newSession() (*ssh.Session, error) {
    connection, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", client.Host, client.Port), client.Config)
    if err != nil {
        return nil, fmt.Errorf("Failed to dial: %s", err)
    }

    session, err := connection.NewSession()
    if err != nil {
        return nil, fmt.Errorf("Failed to create session: %s", err)
    }

    modes := ssh.TerminalModes{
        // ssh.ECHO:          0,     // disable echoing
        ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
        ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
    }

    if err := session.RequestPty("xterm", 0, 200, modes); err != nil {
        session.Close()
        return nil, fmt.Errorf("request for pseudo terminal failed: %s", err)
    }

    return session, nil
}

func SSHAgent() ssh.AuthMethod {
    if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
        return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
    }
    return nil
}

func main() {

    sshConfig := &ssh.ClientConfig{
        User: "admin",
        Auth: []ssh.AuthMethod{
            ssh.Password("password"),
        },
    }
    sshConfig.Ciphers = []string{"aes128-cbc"}

    client := &SSHClient{
        Config: sshConfig,
        Host:   "10.10.10.10",
        Port:   22,
    }

    cmd := &SSHCommand{
        Stdin:  os.Stdin,
        Stdout: os.Stdout,
        Stderr: os.Stderr,
    }

    fmt.Printf("Running commands
")
    if err := client.RunCommand(cmd); err != nil {
        fmt.Fprintf(os.Stderr, "command run error: %s
", err)
        os.Exit(1)
    }

}

As you can see I have hard coded the "en" command in session.Run(). If I add a command after that by simply doing:

err = session.Run("en")
err = session.Run("password")

It gets ignored. Reading https://godoc.org/golang.org/x/crypto/ssh#Session.Shell tells me that this is by design. So my question is : How to set up something that lets me enter commands, read output, parse it, and enter more commands based on that output?

Once I wrap my head around this, I plan on parsing routing tables and issuing commands in response. IE, if route X is missing, add it.

This might not be idiomatic go, I am still learning. I wrote this a while ago to get backups off switches but I think it does what you are asking how to do:

https://github.com/plod/goSwitchBackup/blob/master/main.go

func writeBuff(command string, sshIn io.WriteCloser) (int, error) {
    returnCode, err := sshIn.Write([]byte(command + ""))
    return returnCode, err
}