Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SSH连接超时_Ssh_Go - Fatal编程技术网

SSH连接超时

SSH连接超时,ssh,go,Ssh,Go,我正在尝试使用golang.org/x/crypto/SSH建立SSH连接,我有点惊讶,我似乎无法找到如何超时NewSession函数,实际上我没有看到任何超时的方法。当我尝试连接到一个有问题的服务器时,它会挂起很长时间。我已经写了一些东西来使用选择时间。之后,但它只是感觉像一个黑客。我还没有尝试过的事情是将底层net.Conn保留在我的结构中,然后继续执行Conn.SetDeadline调用。我还没有尝试过这个,因为我不知道crypto/ssh库是否覆盖了这个或类似的内容 有没有人能用这个库让

我正在尝试使用golang.org/x/crypto/SSH建立SSH连接,我有点惊讶,我似乎无法找到如何超时NewSession函数,实际上我没有看到任何超时的方法。当我尝试连接到一个有问题的服务器时,它会挂起很长时间。我已经写了一些东西来使用选择时间。之后,但它只是感觉像一个黑客。我还没有尝试过的事情是将底层net.Conn保留在我的结构中,然后继续执行Conn.SetDeadline调用。我还没有尝试过这个,因为我不知道crypto/ssh库是否覆盖了这个或类似的内容


有没有人能用这个库让死机服务器超时的好方法?或者有人知道更好的库吗?

使用ssh包透明地处理这个问题的一种方法是通过自定义net.Conn创建一个空闲超时的连接,该连接为您设置最后期限。但是,这将导致连接上的后台读取超时,因此我们需要使用ssh keepalives保持连接打开。根据您的使用情况,简单地使用ssh keepalives作为断开连接的警报可能就足够了

// Conn wraps a net.Conn, and sets a deadline for every read
// and write operation.
type Conn struct {
    net.Conn
    ReadTimeout  time.Duration
    WriteTimeout time.Duration
}

func (c *Conn) Read(b []byte) (int, error) {
    err := c.Conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
    if err != nil {
        return 0, err
    }
    return c.Conn.Read(b)
}

func (c *Conn) Write(b []byte) (int, error) {
    err := c.Conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
    if err != nil {
        return 0, err
    }
    return c.Conn.Write(b)
}
然后,您可以使用net.DialTimeout或net.Dialer获取连接,将其包装在带有超时的Conn中,并将其传递到ssh.NewClientConn

在上设置超时


当你打电话时,超时时间将被传递到。

是的,我认为用你设定的最后期限进行新客户端操作是正确的。评论不回答,因为我对ssh包不太熟悉。grep-R Deadline src/golang.org/x/crypto/ssh的输出让我觉得这个包不会妨碍你,但不会帮你;唯一提到的似乎与ssh端口转发有关。是的,SetDeadline有效,但我必须说,用于建立连接的库中缺少超时似乎是一个重大疏忽。。不要听起来忘恩负义或者其他什么,如果我有时间,我会看看我是否可以帮助包括它。对我来说有点陌生的是,当我建立到我的一个服务器的连接时,我知道它已经死了/有问题,我无法从终端ssh到它,我根本没有收到ssh.NewClientConn的错误,也没有返回一个无客户机。不管怎么说,这就是我问题的主要原因,它试图用一个作为活动服务器传递的死机服务器调用NewSession。如果ssh.NewClientConn返回ok,那么服务器并不是真的死机,因为它可以完成ssh握手。@user3591723-我想原理是如果你可以使用另一个标准包来实现一项功能,stdlib的作者通常不会提供另一种方法,即使更方便。例如,人们经常使用Go的net/http编写返回JSON的服务,您可以想象方便的方法使构建这些服务变得更容易,但net/http本身并没有提供这些服务;net/http必须连接到编码/json和其他代码。这显然比我想到的更明显。可能会实现类似的功能。我更喜欢这个答案
func SSHDialTimeout(network, addr string, config *ssh.ClientConfig, timeout time.Duration) (*ssh.Client, error) {
    conn, err := net.DialTimeout(network, addr, timeout)
    if err != nil {
        return nil, err
    }

    timeoutConn := &Conn{conn, timeout, timeout}
    c, chans, reqs, err := ssh.NewClientConn(timeoutConn, addr, config)
    if err != nil {
        return nil, err
    }
    client := ssh.NewClient(c, chans, reqs)

    // this sends keepalive packets every 2 seconds
    // there's no useful response from these, so we can just abort if there's an error
    go func() {
        t := time.NewTicker(2 * time.Second)
        defer t.Stop()
        for range t.C {
            _, _, err := client.Conn.SendRequest("keepalive@golang.org", true, nil)
            if err != nil {
                return
            }
        }
    }()
    return client, nil
}
cfg := ssh.ClientConfig{
    User: "root",
    Auth: []ssh.AuthMethod{
        ssh.PublicKeys(signer),
    },
    HostKeyCallback: ssh.FixedHostKey(hostKey),
    Timeout:         15 * time.Second, // max time to establish connection
}

ssh.Dial("tcp", ip+":22", &cfg)