我正在尝试使用golang.org/x/crypto/ssh
建立SSH连接,我有点惊讶我似乎无法找到如何超时NewSession
功能(我实际上没有看到任何方法超时任何事情)。当我尝试连接到有问题的服务器时,这只会挂起很长一段时间。我写了一些东西select
和time.After
,但它只是感觉像是一个黑客。我还没有尝试过的是在我的结构中保留基础net.Conn
并继续进行Conn.SetDeadline()
调用。还没有尝试过这个,因为我不知道crypto / ssh库是否覆盖了这个或类似的东西。
任何人都有一个很好的方法来使用此库超时死机服务器?或者有人知道更好的图书馆吗?
答案 0 :(得分:17)
使用ssh包透明地处理此问题的一种方法是通过自定义net.Conn
创建一个空闲超时的连接,为您设置截止日期。但是,这会导致连接上的后台读取超时,因此我们需要使用ssh keepalive来保持连接打开。根据您的使用情况,只需使用ssh keepalive作为死连接的警报即可。
// 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
。
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
}
答案 1 :(得分:4)
在ssh.ClientConfig
上设置超时。
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)
当您致电ssh.Dial
时,超时时间将传递给net.DialTimeout
。