首页 > 解决方案 > 在golang ssh会话关闭中将EOF作为错误

问题描述

我正在使用“ssh”golang 模块,我想知道我是否实现了它(或尝试)。session.Close() 中的“EOF”是否是预期的错误?在我在网上看到的示例中,没有人检查 session.Close() 错误。这是我应该忽略或处理的事情吗?据我所知,服务器也不会出现错误。我想知道我是否没有正确执行命令,或者没有正确读取缓冲区。

这是我的代码:

package main

import (
    "bytes"
    "fmt"
    "strings"

    "golang.org/x/crypto/ssh"
)

func main() {
    sshConfig := &ssh.ClientConfig{
        User: “my_username”,
        Auth: []ssh.AuthMethod{
            ssh.Password(“my password”),
        },
        HostKeyCallback: ssh.InsecureIgnoreHostKey(),
    }
    connection, err := ssh.Dial("tcp", "localhost:22", sshConfig)
    if err != nil {
        fmt.Printf("Failed to dial: %s\n", err)
        return
    }

    defer func() {
        if err := connection.Close(); err != nil {
            fmt.Println("Received an error closing the ssh connection: ", err)
        } else {
            fmt.Println("No error found closing ssh connection")
        }
    }()

    session, err := connection.NewSession()
    if err != nil {
        fmt.Printf("Failed to create session: %s\n", err)
        return
    }

    defer func() {
        if err := session.Close(); err != nil {
            fmt.Println("Received an error closing the ssh session: ", err)
        } else {
            fmt.Println("No error found closing ssh session")
        }
    }()
    fmt.Println("created session")
    var stdOut bytes.Buffer
    var stdErr bytes.Buffer

    session.Stdout = &stdOut
    session.Stderr = &stdErr
    err = session.Run("pwd")
    fmt.Println("Executed command")

    fmt.Println("Command stdOut is:", strings.TrimRight(stdOut.String(), "\n"), " --- stdError is:", strings.TrimRight(stdErr.String(), "\n"))

}

我得到的输出是:

$ go run main.go
created session
Executed command
Command stdOut is: /Users/my_username  --- stdError is: 
Received an error closing the ssh session:  EOF
No error found closing ssh connection
$ 

有什么建议吗?

标签: gossh

解决方案


这似乎类似于golang/go/issue 31401(然后指的是问题 32453:“ x/crypto/ssh:在发送 EOF 消息时调用 session.Run() 后运行 session.Wait() 的语义”)

返回错误是因为会话已经关闭(由Run())。
SSH 连接泄漏是因为它从不关闭——从返回的客户端对象Dial()被丢弃,但这是需要关闭以清理底层 TCP 连接的对象。

顺便说一句,这似乎是一个可以正确使用的微妙 API。
会话可以在任何时候被另一方异步关闭,因此正确编写的代码总是有可能从中获取 EOFClose()

所以你可能想测试那个特定的错误,并在你的 defer 函数中忽略它。


推荐阅读