duanchan9354 2018-01-26 19:32
浏览 177
已采纳

Golang-过滤活动SSH会话的标准输出

I'm writing an SSH client in Go that connects to a switch and runs a list of configuration commands. So far, I am able to successfully connect to a switch, run the desired commands, and print the output of the session. The problem comes when the switch is expecting a , space, or "q" to be entered when a command's output is too long. For example:

switch#show int status

Port      Name               Status       Vlan       Duplex  Speed Type
Gi1/0/1                      notconnect   100          auto   auto 10/100/1000BaseTX
Gi1/0/2                      connected    915        a-full  a-100 10/100/1000BaseTX
Gi1/0/3                      notconnect   100          auto   auto 10/100/1000BaseTX
Gi1/0/4                      notconnect   100          auto   auto 10/100/1000BaseTX
Gi1/0/5                      notconnect   230          auto   auto 10/100/1000BaseTX
...
Po1       sw-sww-100-sww-0-0 connected    trunk      a-full    10G
 --More-- # Program hangs here; expecting a new line, space, or 'q'

The --More-- prompt is not actually printed to the screen, so simply checking if the current line of Stdout contains --More-- and sending a , space, or "q" does not work.

Gif of <code>--More--</code> prompt disappearing.

In addition to fixing this problem, I'd like to filter Stdout of the session so that the only thing printed is the output of each command. In other words, I don't want the switch's prompt to be printed to the terminal.

To sum up:

  1. How to capture and print only the output of each command?
  2. How to send a new line, space, or letter "q" when prompted?

Any help is appreciated. Here is my code:

package main

import (
    "bufio"
    "fmt"
    "golang.org/x/crypto/ssh"
    "io"
    "log"
    "os"
    "time"
)

type Device struct {
    Config  *ssh.ClientConfig
    Client  *ssh.Client
    Session *ssh.Session
    Stdin   io.WriteCloser
    Stdout  io.Reader
    Stderr  io.Reader
}

func (d *Device) Connect() error {
    client, err := ssh.Dial("tcp", os.Args[1]+":22", d.Config)
    if err != nil {
        return err
    }
    session, err := client.NewSession()
    if err != nil {
        return err
    }
    sshIn, err := session.StdinPipe()
    if err != nil {
        return err
    }
    sshOut, err := session.StdoutPipe()
    if err != nil {
        return err
    }
    sshErr, err := session.StderrPipe()
    if err != nil {
        return err
    }
    d.Client = client
    d.Session = session
    d.Stdin = sshIn
    d.Stdout = sshOut
    d.Stderr = sshErr
    return nil
}

func (d *Device) SendCommand(cmd string) error {
    if _, err := io.WriteString(d.Stdin, cmd+"
"); err != nil {
        return err
    }
    return nil
}

func (d *Device) SendConfigSet(cmds []string) error {
    for _, cmd := range cmds {
        if _, err := io.WriteString(d.Stdin, cmd+"
"); err != nil {
            return err
        }
        time.Sleep(time.Second)
    }
    return nil
}

func (d *Device) PrintOutput() {
    r := bufio.NewReader(d.Stdout)
    for {
        text, err := r.ReadString('
')
        fmt.Printf("%s", text)
        if err == io.EOF {
            break
        }
    }
}

func (d *Device) PrintErr() {
    r := bufio.NewReader(d.Stderr)
    for {
        text, err := r.ReadString('
')
        fmt.Printf("%s", text)
        if err == io.EOF {
            break
        }
    }
}

func main() {
    sshConf := ssh.Config{}
    sshConf.Ciphers = append(sshConf.Ciphers, "aes128-cbc", "3des-cbc", "blowfish-cbc", "arcfour")
    config := &ssh.ClientConfig{
        Config: sshConf,
        User:   "mwalto7",
        Auth: []ssh.AuthMethod{
            ssh.Password("Lion$Tiger$Bear$"),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
        Timeout:         time.Second * 5,
    }

    sw := &Device{Config: config}

    fmt.Println("Connecting to ", os.Args[1])
    if err := sw.Connect(); err != nil {
        log.Fatal(err)
    }
    defer sw.Client.Close()
    defer sw.Session.Close()
    defer sw.Stdin.Close()

    if err := sw.Session.Shell(); err != nil {
        log.Fatal(err)
    }

    commands := []string{"show int status", "exit"}
    if err := sw.SendConfigSet(commands); err != nil {
        log.Fatal(err)
    }

    sw.Session.Wait()

    sw.PrintOutput()
    sw.PrintErr()
}
  • 写回答

1条回答 默认 最新

  • doushui3216 2018-03-15 19:00
    关注

    I fixed this problem by sending the command terminal length 0 just after connecting to the switch, before sending the rest of the commands. This disabled the —More— prompt by setting the switch’s terminal height to 0, allowing the whole output of a command to be displayed.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题