Geo*_* K. 5 ssh concurrency channel go
我有一组服务器,我正在尝试与其建立 SSH 连接,并且我正在为我必须建立的每个新 SSH 连接生成一个新的 goroutine。然后我将连接的结果(连同错误(如果有))发送到一个通道,然后从通道中读取。这个程序有点工作,但即使我关闭了频道,它最终还是冻结了。
这是我到目前为止:
package main
import (
"fmt"
"net"
"sync"
"github.com/awslabs/aws-sdk-go/aws"
"github.com/awslabs/aws-sdk-go/service/ec2"
)
// ConnectionResult container
type ConnectionResult struct {
host string
message string
}
func main() {
cnres := make(chan ConnectionResult)
ec2svc := ec2.New(&aws.Config{Region: "us-east-1"})
wg := sync.WaitGroup{}
params := &ec2.DescribeInstancesInput{
Filters: []*ec2.Filter{
&ec2.Filter{
Name: aws.String("instance-state-name"),
Values: []*string{
aws.String("running"),
},
},
},
}
resp, err := ec2svc.DescribeInstances(params)
if err != nil {
panic(err)
}
for _, res := range resp.Reservations {
for _, inst := range res.Instances {
for _, tag := range inst.Tags {
if *tag.Key == "Name" {
host := *tag.Value
wg.Add(1)
go func(hostname string, cr chan ConnectionResult) {
defer wg.Done()
_, err := net.Dial("tcp", host+":22")
if err != nil {
cr <- ConnectionResult{host, "failed"}
} else {
cr <- ConnectionResult{host, "succeeded"}
}
}(host, cnres)
}
}
}
}
for cr := range cnres {
fmt.Println("Connection to " + cr.host + " " + cr.message)
}
close(cnres)
defer wg.Wait()
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?有没有更好的方法在 Go 中进行并发 SSH 连接?
上面的代码陷入了循环range cnres for。正如优秀的“Go by example”中所指出的,range只会在封闭的通道上退出。
解决这个困难的一种方法是range cnres在另一个 goroutine 中运行迭代。然后您可以wg.Wait(),然后是close()频道,如下所示:
...
go func() {
for cr := range cnres {
fmt.Println("Connection to " + cr.host + " " + cr.message)
}
}()
wg.Wait()
close(cnres)
Run Code Online (Sandbox Code Playgroud)
hostname顺便说一句(与被卡住的代码无关),我认为目的是在函数中使用Dial(),以及后续的通道写入,而不是host.
| 归档时间: |
|
| 查看次数: |
1167 次 |
| 最近记录: |