Mike  Hols
Mike Hols

Reputation: 58

How to simulate a keypress when using ssh and interactive shell

Stuck on keypress

I'm trying to create a script that makes a back-up from a HP proCurve switch. For this I'm using the package golang.org/x/crypto/ssh.

Golang is not new to me and I have quite a bit of "Go" knowledge. But I get stuck after establishing the connection. The switch is asking me to press any key to continue but I don't know how to simulate a keypress. (see image below)

Terminal response


Current code

This is the code that I'm currently using:

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "os"

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

type password string

func main() {

    host := "192.168.2.43:22"
    user := "admin"
    pass := "admin"

    config := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(pass),
        },
        Config: ssh.Config{
            KeyExchanges: []string{"diffie-hellman-group-exchange-sha1", "diffie-hellman-group1-sha1"},
        },

        HostKeyCallback: ssh.HostKeyCallback(func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }),
    }
    conn, err := ssh.Dial("tcp", host, config)
    if err != nil {
        panic("Failed to dial: " + err.Error())
    }
    defer conn.Close()

    // Each ClientConn can support multiple interactive sessions,
    // represented by a Session.
    session, err := conn.NewSession()
    if err != nil {
        panic("Failed to create session: " + err.Error())
    }
    defer session.Close()

    // Set IO
    session.Stdout = os.Stdout
    session.Stderr = os.Stderr
    in, _ := session.StdinPipe()

    // Set up terminal modes
    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
    }

    // Request pseudo terminal
    if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
        log.Fatalf("request for pseudo terminal failed: %s", err)
    }

    // Start remote shell
    if err := session.Shell(); err != nil {
        log.Fatalf("failed to start shell: %s", err)
    }

    // Accepting commands
    for {

        reader := bufio.NewReader(os.Stdin)
        str, _ := reader.ReadString('\n')
        fmt.Fprint(in, str)

        // Solutition to keypress to continue

        fmt.Fprint(in, " \n")
        fmt.Fprint(in, "show run \n")

    }

}


What I try to achieve

But when I'm pressing any key manually, the script will run all the commands perfectly. So does anyone know how I can simulate any key within the code below:


    for {

        reader := bufio.NewReader(os.Stdin)
        str, _ := reader.ReadString('\n')
        fmt.Fprint(in, str)

        // Solutition to keypress to continue

        fmt.Fprint(in, " \n")
        fmt.Fprint(in, "show run \n")

    }

Upvotes: 3

Views: 1729

Answers (1)

Tyler Kropp
Tyler Kropp

Reputation: 573

You are reading from the standard input before you ever write to the ssh connection. As a result, this screen can only by skipped by manual intervention.

The reading of the command line's standard input should come after any initial commands you want to run on the host, so it would be organized like this:

    // Requires keypress to continue
    fmt.Fprint(in, " \n")
    // List out useful information
    fmt.Fprint(in, "show run \n")

    // Forward user commands to the remote shell
    for {
        reader := bufio.NewReader(os.Stdin)
        str, _ := reader.ReadString('\n')
        fmt.Fprint(in, str)
    }

Upvotes: 1

Related Questions