multiple commands in one ssh session

2,652 views
Skip to first unread message

Dominik Link

unread,
May 18, 2017, 6:23:57 AM5/18/17
to golang-nuts

Hi


I would like to run multiple ssh commands within the same 'context' as if it would be using putty when connecting to a cisco device.

Here are two examples of what i would need to send to the device:



1) Setting the terminal width to 0 in order to remove the line breaks. This makes parsing the output of the following command easier.

Switch#terminal width 0
Switch#show vlan brief

    VLAN Name                             Status    Ports
    ---- -------------------------------- --------- -------------------------------
    1    default                          active    Et0/0, Et0/1, Et0/2, Et0/3
    ...
    ...



2) Configure an IP address of an interface. When connecting with ssh, I start in the 'enable' mode due to the user privileges. I need to get in the config mode first. Afterwards, I need to get in the interface config mode and can finally set the address.

Router#configure terminal
    Enter configuration commands, one per line.  End with CNTL/Z.
Router(config)#interface e3/2
Router(config-if)#ip address 172.16.1.1 255.255.255.0




I can run a single command easily with session.Run() but as I described, I need to be able to run multiple commands and parse their output within a single 'context'.

How could this behavior be achieved with crypto/ssh? When I try to create a new session after the first session.run(), it always returns with an error: "EOF".

I just wanted to try whether the context will stay the same but it won't even come that far.


//create session 1 and go into config mode
session, err = client.NewSession()
if err != nil {
    panic("Failed to create session: " + err.Error())
}
if err := session.Run("conf t"); err != nil {
    panic("Failed to run: " + err.Error())
}
session.Close()

//create session 2 and go into if mode
session, err = client.NewSession()
if err != nil {
    //Error will be EOF
    panic("Failed to create session: " + err.Error())
}
if err := session.Run("int e3/2"); err != nil {
    panic("Failed to run: " + err.Error())
}
session.Close()


Thanks,
Dominik


I also posted this question in stackoverflow

Matt Harden

unread,
May 20, 2017, 2:59:41 PM5/20/17
to Dominik Link, golang-nuts
Instead of session.Run, use session.Shell. To interact with the shell, you will need to connect to at least Stdin, probably using StdinPipe() (NOTE I left out error handling):
session, err := client.NewSession()
in, err := session.StdinPipe()
out, err := session.StdoutPipe()
session.Stderr = out  // this will send stderr to the same pipe
err = session.Shell()
go readOutput(out)  // run a function to read the output of the commands

// send the commands
err = fmt.Println(in, "conf t")
// probably wait for the right output before continuing
//  - this requires synchronization with the readOutput goroutine
err = fmt.Println(in, "int e3/2")
// and so on
const ctrlZ = byte(25)
err = in.Write([]byte{ctrlZ})
I hope this helps!

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

hil...@gmail.com

unread,
Dec 9, 2017, 6:38:28 AM12/9/17
to golang-nuts
Hi Dominik. Have you finally found the solution? I'm working on similar task to run commands on cisco routers. Could you share you code for this?

Matt Harden

unread,
Dec 30, 2017, 12:40:48 AM12/30/17
to hil...@gmail.com, golang-nuts
Did you try out my suggestion in reply to Dominik, namely to use session.Shell instead of session.Run?

--
Reply all
Reply to author
Forward
0 new messages