我张贴了一个类似的问题here,以便从telnet会话中阅读。
我正在尝试从golang中的SSH会话读取数据。我编写了以下函数来尝试实现这一目标。
我遇到了一个问题,我试图从stdout读取内容,它为空,导致我的程序锁定。为了解决这个问题,我编写了BufferSocketData,它检查ReadDataFromSocket应该附加到的通道,如果它有数据,则将其添加到缓冲区。如果1秒钟后仍未收到任何数据,则会停止读取。
这不能正常工作,我不确定为什么。即使缓冲区中有数据,也只有第一个读取获得新数据,后续读取才会返回空字符串。
在上一个问题中,我可以使用SetReadDeadline限制从套接字读取的时间,是否可以在SSH会话中使用类似的功能?还是我需要一起使用其他策略?
/*
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
}
}
如果您需要其他任何信息,请告诉我。
答案 0 :(得分:1)
为该会话启动单个读取器goroutine。这个goroutine从会话中读取数据并将数据发送到通道。
在主goroutine中,循环选择包含接收数据和超时情况的案例。适当处理每种情况。
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
}
}
}