Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.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
Go 强制关闭SSH客户端会话_Go_Ssh - Fatal编程技术网

Go 强制关闭SSH客户端会话

Go 强制关闭SSH客户端会话,go,ssh,Go,Ssh,我已经编写了一个SSH客户端来连接网络设备,并且在运行命令超过25秒时通过“选择”设置超时。我注意到一些设备有另一个IOS,一旦触发超时,它就不能通过Close()方法删除SSH会话,从而导致GoRouting泄漏。我需要保持客户端并断开会话,以便为下一个命令做好准备。看起来goroutine在那个时候不会永远终止!你们知道吗 go func() { r <- s.Run(cmd) }() select { case err := &l

我已经编写了一个SSH客户端来连接网络设备,并且在运行命令超过25秒时通过“选择”设置超时。我注意到一些设备有另一个IOS,一旦触发超时,它就不能通过Close()方法删除SSH会话,从而导致GoRouting泄漏。我需要保持客户端并断开会话,以便为下一个命令做好准备。看起来goroutine在那个时候不会永远终止!你们知道吗

    go func() {
       r <- s.Run(cmd)
    }()

    select {
       case err := <-r:
         return err
       case <-time.After(time.Duration(timeout) * time.Second):
         s.Close()
         return fmt.Errorf("timeout after %d seconds", timeout)
    }
例程===================================runtime.goexit in/usr/local/go/src/runtime/asm_amd64.s

     0     2.78GB (flat, cum) 99.93% of Total

     .          .   1993:   RET

     .          .   1994:

     .          .   1995:// The top-most function running on a goroutine

     .          .   1996:// returns to goexit+PCQuantum.

     .          .   1997:TEXT runtime·goexit(SB),NOSPLIT,$0-0

     .     2.78GB   1998:   BYTE    $0x90   // NOP

     .          .   1999:   CALL    runtime·goexit1(SB) // does not return

     .          .   2000:   // traceback from goexit1 must hit code range of goexit

     .          .   2001:   BYTE    $0x90   // NOP

     .          .   2002:


     .          .   2003:TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8

通道
r
阻止Go例程返回,因为它没有被清空。我已经编写了您的代码的改编版本,并插入了一个等待组来演示问题:

func main() {
    var wg sync.WaitGroup // This is only added for demonstration purposes
    s := new(clientSession)

    r := make(chan error)

    go func(s *clientSession) {
        wg.Add(1)
        r <- s.Run()
        wg.Done() // Will only be called after s.Run() is able to return
    }(s)

    fmt.Println("Client has been opened")

    select {
    case err := <-r:
        fmt.Println(err)
    case <-time.After(1 * time.Second):
        s.Close()
        fmt.Println("Timed out, closing")
    }

    wg.Wait() // Waits until wg.Done() is called.

    fmt.Println("Main finished successfully")
}
这是因为我们的代码在
wg.Wait()
行上处于死锁状态。这表明Go例程中的
wg.Done()
从未到达

正如评论所指出的,缓冲通道可以在这里提供帮助。但只有在调用
s.Close()

运行正常,但错误已丢失:

$ go run buffered.go
Client has been opened
Timed out, closing
Main finished successfully
另一种选择是将通道完全排空1次:

select {
    case err := <-r:
        fmt.Println(err)
    case <-time.After(1 * time.Second):
        s.Close()
        fmt.Println("Timed out, closing")
        fmt.Println(<-r)
    }
当我们运行时,我们看到错误也被打印出来:

$ go run incorrect.go
Client has been opened
Timed out, closing
Run() closed
Main finished successfully

在现实世界中,一个将运行多个围棋例程。因此,您需要在
循环中使用一些计数器,或进一步利用等待组功能。

是否缓冲
r
通道?当您超时时,没有接收器接受来自
s.Run的结果。您可能仍然需要实际终止远程进程;您是否尝试过在超时时使用
s.Signal
将其杀死?同样,是
r
缓冲了吗?它需要缓冲,否则goroutine无法返回。不要关闭会话以中止,杀死进程并等待它(Run正在调用Wait you)我相信由s触发的进程。Run没有正确停止,因此,它无法取消分配资源。您是否尝试将sigterm/sig kill发送到该进程?使用Start和wait代替Run,就像
$ go run buffered.go
Client has been opened
Timed out, closing
Main finished successfully
select {
    case err := <-r:
        fmt.Println(err)
    case <-time.After(1 * time.Second):
        s.Close()
        fmt.Println("Timed out, closing")
        fmt.Println(<-r)
    }
X:
    for {
        select {
        case err := <-r:
            fmt.Println(err)
            break X // because we are in main(). Normally `return err`
        case <-time.After(1 * time.Second):
            s.Close()
            fmt.Println("Timed out, closing")
        }
    }
$ go run incorrect.go
Client has been opened
Timed out, closing
Run() closed
Main finished successfully