从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.

ssh
doutuohan6606
doutuohan6606 主要问题是,在最初调用GetData之后,我再也没有得到任何新数据,我猜测它与我的go例程和通道使用有关。是的,如果在合理的时间内没有找到匹配项,我会检查s.Buffer来查看它是否与某些正则表达式或超时匹配。
大约 2 年之前 回复
douzhongqiu5032
douzhongqiu5032 每次对GetData的调用都会启动一个goroutine来读取连接,并且在GetData返回时可以将这些goroutine挂起。这些goroutine最终将读取数据,但是数据将被忽略。描述您要解决的高级问题。您是否在s.Buffer上调用正则表达式匹配,直到找到匹配或超时?
大约 2 年之前 回复
dongyong8491
dongyong8491 是的,我有一个函数可以检查缓冲区中的正则表达式是否匹配,如果找不到匹配项,并且尚未发生超时,它将再次调用GetData。
大约 2 年之前 回复
douzhuan1467
douzhuan1467 GetData是否被多次调用?
大约 2 年之前 回复

1个回答

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
        }
    }
}
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问