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

I am writing a CLI for configuring Cisco access points through Cisco wireless controllers over SSH in Go 1.9.2. I am using the golang.org/x/crypto/ssh package to handle connecting to the wireless controllers. I am able to successfully SSH to the desired controller, but I'm running into problems when attempting to send commands to the controller. I know the problem is due to the controller's prompt and output to Stdout. When manually connecting to a controller, this is the output:

$ ssh <controller_ip>


(Cisco Controller)
User: username
Password:****************
(Cisco Controller) >

Everything I have read and all the code examples I have seen of similar problems use the bufio package to create a reader to deal with the prompts/output. I can get that to partially work, but the program hangs after printing the line (Cisco Controller) before the username prompt, like this:

$ go run main.go


(Cisco Controller)
# infinite blinking cursor

I know this is because the controller is expecting a username to be passed.

My question, then, is how do I correctly handle parsing the output and send commands to the controller? I'm new to GO and network programming in general, so any help is appreciated. Here is my full code so far:

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
}

This is the output I get when running the program:

$ go run main.go
2017/12/28 14:13:28 ssh: command show failed
exit status 1
ssh
duan47676379
duan47676379 这是我运行程序的输出:$gorunmain.go2017/12/2814:13:28ssh:命令显示失败的退出状态1
接近 3 年之前 回复
douchuose2514
douchuose2514 我尝试使用“运行”发送“显示”。我在atm上没有计算机,但是我知道错误的退出状态为1
接近 3 年之前 回复
douganggu4392
douganggu4392 你寄了什么?有什么错误?
接近 3 年之前 回复
douche1936
douche1936 我已经做到了。无论我传递运行什么命令,都会对该命令给出SSH错误
接近 3 年之前 回复
douxuanwei1980
douxuanwei1980 您没有按原样发送任何命令。首先查看Session.Run
接近 3 年之前 回复
dongli4274
matlabmann 我想发送多个完整的命令
接近 3 年之前 回复
doubengman2072
doubengman2072 您到底想做什么?您要进行互动式会议吗?您是否要像使用“expect”那样使交互式会话自动化?您要发送完整的命令来执行吗?
接近 3 年之前 回复

1个回答

Here is an example: https://github.com/Scalingo/go-ssh-examples/blob/master/client.go

Shouldn't you need to start a new session to initiate commands?

Hope it helps.

func connectToHost(user, host string) (*ssh.Client, *ssh.Session, error) {
    var pass string
    fmt.Print("Password: ")
    fmt.Scanf("%s
", &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
}
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐