duanlou2917 2018-06-26 17:11
浏览 188
已采纳

从SSH会话Golang读取数据

I posted a similar question here for reading from a telnet session.

I am trying to read data from an SSH session in golang. I wrote the following functions to try to accomplish this.

I was running into an issue where I was trying to read from stdout and it was empty and it caused my program to lock. To try to work around this I wrote BufferSocketData, it checks the channel ReadDataFromSocket is supposed to append to and if it has data it adds it to the buffer. If after 1 second it still hasn't received any data it stops the read.

This isn't working correctly though and I'm unsure why. Only the first read gets new data subsequent reads return an empty string even if there is data in the buffer.

In my previous question I was able to use SetReadDeadline to limit the amount of time reading from the socket, is there something similar I can use with an SSH session? or do I need to use a different strategy all together?

/*
ReadDataFromSocket - Attempts to read any data in the socket.
*/
func ReadDataFromSocket(sock io.Reader, c chan string) {
    var recvData = make([]byte, 1024)
    var numBytes, _ = sock.Read(recvData)
    c <- string(recvData[:numBytes])
}

/*
BufferSocketData - Read information from the socket and store it in the buffer.
*/
func (s *SSHLib) BufferSocketData(inp chan string, out chan string) {
    var data string
    var timeout int64 = 1000 // 1 second timeout.
    var start = utils.GetTimestamp()

    for utils.GetTimestamp()-start < timeout {
        select {
        case data = <-inp:
        default:
        }
        if data != "" {
            break
        }
    }
    out <- data
}

/*
GetData - Start goroutines to get and buffer data.
*/
func (s *SSHLib) GetData() {
    var sockCh = make(chan string)
    var buffCh = make(chan string)

    go ReadDataFromSocket(s.Stdout, sockCh)
    go s.BufferSocketData(sockCh, buffCh)

    var data = <-buffCh

    if data != "" {
        s.Buffer += data
    }
}

Please let me know if you need any other information.

  • 写回答

1条回答 默认 最新

  • dpwtr666638 2018-06-26 19:02
    关注

    Start a single reader goroutine for the session. This goroutine reads from the session and sends data to a channel.

    In the main goroutine, select in a loop with cases for data received and timeout. Process each case as appropriate.

    type SSHLib struct {
        Stdout io.Reader
        Buffer string
        Data   chan string  // <-- Add this member
    }
    
    // New creates a new SSHLib. This example shows the code 
    // relevant to reading stdout only. 
    func New() *SSHLib {
        s := &SSHLib{Data: make(chan string)}
        go s.Reader()
        return s
    }
    
    // Reader reads data from stdout in a loop.
    func (s *SSHLib) Reader() {
        var data = make([]byte, 1024)
        for {
            n, err := s.Stdout.Read(data)
            if err != nil {
                // Handle error
                return
            }
            s.Data <- string(data[:n])
        }
    }
    
    // GetData receives data until regexp match or timeout.
    func (s *SSHLib) GetData() {
        t := time.NewTimer(time.Second)
        defer t.Stop()
        for {
            select {
            case d := <-s.Data:
                s.Buffer += d
                // Check for regexp match in S.Buffer
            case <-t.C:
                // Handle timeout
                return
            }
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作