使用Golang实现SSH会话输出的实时过滤
使用Golang实现SSH会话输出的实时过滤
大家好!
我对Go语言还比较生疏,所以这个问题可能显得有点新手。无论如何...
我需要过滤来自SSH会话的持续输出流。
使用的库是"golang.org/x/crypto/ssh"。
在尝试实现过滤SSH会话中每行新输入以匹配特定字符串的功能时,我对bytes.Buffer/io.Reader感到相当困惑。
我目前的代码似乎是传递了一个指向bytes.Buffer对象的指针:
```go
if err := session.RequestPty("vt100", 80, 40, modes); err != nil {
//if err := session.RequestPty("vt220", 80, 40, modes); err != nil {
log.Printf("[ERROR] SSH PTY Error for %s (%s)", "target", err.Error())
return
}
if err := session.Shell(); err != nil {
log.Printf("[ERROR] SSH Shell Setup Error for %s (%s)", "target", err.Error())
return
}
r, err := session.StdoutPipe()
if err != nil {
log.Printf("[ERROR] SSH Output Pipe Error for %s (%s)", "target", err.Error())
return
}
var buff bytes.Buffer
session.Stdout = &buff
在阅读相关资料后,建议的处理方法是使用类似这样的代码:
func main() {
input := "foo\nbar\nbaz"
scanner := bufio.NewScanner(strings.NewReader(input))
// 实际上不需要设置,因为这是默认的分割函数
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
但是,由于这个方法需要io.Reader对象,我不知道如何将我的bytes.Buffer与之连接。再次说明,我是个初学者,可能还没掌握Go语言的基础知识。
我应该如何继续?如果不是使用上述代码,我也很乐意改变方法。我知道SSH库中有StdOutPipe可用,但我不确定这是否有帮助。
来自SSH会话的输出本质上是网络设备上的调试命令。
非常感谢!
更多关于使用Golang实现SSH会话输出的实时过滤的实战教程也可以访问 https://www.itying.com/category-94-b0.html
嗨,我不太明白你想做什么;听起来你是在尝试过滤掉不匹配预期子字符串的行。如果是这种情况,你不能直接用 grep 过滤数据吗?
// 代码示例保留原样
func main() {
fmt.Println("hello world")
}
更多关于使用Golang实现SSH会话输出的实时过滤的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
引用 mnantel:
然而,由于此方法需要 io.Reader 对象,我不知道如何将我的 bytes.Buffer 与此关联。我确实是个初学者,可能还没掌握 Go 的基础知识。
你好。bytes.Buffer 实现了 reader 接口(参见 bytes 包 - bytes - Go 语言包),因此你可以直接使用它。
你可以使用 StdoutPipe 来获取 SSH 会话的实时输出流,然后通过 bufio.Scanner 逐行处理并过滤。以下是一个完整的示例:
package main
import (
"bufio"
"log"
"strings"
"golang.org/x/crypto/ssh"
)
func main() {
// SSH 连接配置和建立(示例)
config := &ssh.ClientConfig{
User: "username",
Auth: []ssh.AuthMethod{
ssh.Password("password"),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
client, err := ssh.Dial("tcp", "host:22", config)
if err != nil {
log.Fatal("Failed to dial: ", err)
}
defer client.Close()
session, err := client.NewSession()
if err != nil {
log.Fatal("Failed to create session: ", err)
}
defer session.Close()
modes := ssh.TerminalModes{
ssh.ECHO: 0,
ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400,
}
if err := session.RequestPty("vt100", 80, 40, modes); err != nil {
log.Fatal("Request for pseudo terminal failed: ", err)
}
// 获取标准输出管道
stdout, err := session.StdoutPipe()
if err != nil {
log.Fatal("Unable to setup stdout: ", err)
}
if err := session.Shell(); err != nil {
log.Fatal("Failed to start shell: ", err)
}
// 使用 bufio.Scanner 实时读取输出
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
// 过滤包含特定字符串的行
if strings.Contains(line, "特定字符串") {
log.Printf("过滤后的输出: %s", line)
}
}
if err := scanner.Err(); err != nil {
log.Printf("读取输出时出错: %v", err)
}
session.Wait()
}
关键点:
- 使用
session.StdoutPipe()获取io.Reader接口 bufio.NewScanner可以直接使用这个 Reader- 在
scanner.Scan()循环中实时处理每一行输出 - 在循环内添加你的过滤逻辑
对于你的原始代码,主要问题是直接将 bytes.Buffer 设置为 session.Stdout,这会缓冲所有输出而不是实时处理。使用 StdoutPipe 配合 Scanner 是更合适的实时处理方式。
如果需要同时处理标准错误输出,可以类似地使用 session.StderrPipe()。

