Hi I am new to gaoling and I am trying ssh into hundreds of machines and check for a successful connection. I am using goroutines and channels for this. My code runs fine on a small sample size but on larger ones it only completes sometimes while many times it does not.
results := make(chan string)
errors := make(chan string)
for i := 0; i < len(hosts); i++ {
host := hosts[i]
go func(host string) {
conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", host, port), sshConfig)
if err != nil {
errors <- "Connection Failed " + host
} else if conn != nil {
results <- host
conn.Close()
}
}(host)
}
for i := 0; i < len(hosts); i++ {
select {
case res := <-results:
resList = append(resList, res)
case err := <-errors:
fmt.Println(err)
}
}
close(results)
close(errors)
On a first glance, I would try closing conn before sending host to results, to avoid open connections piling up (and perhaps hitting some limit) while the goroutines wait for the unbuffered results channel to become available.
Thanks for the suggestion. I am trying that now but I have a feeling that is not the reason. I am attempting to connect to around 650 machines and expecting only two successful hosts. I see the output get spit out really fast and then it hangs when most/all of the output is completed
edit: still running into this problem. When it reaches the last few hosts it hangs
There are several design glitches here like using for loop instead of range, then “else if” without a real reason (the first condition can just return), then close can be defered. But this has nothing to do with the problem
Try to put debugging output before and after ssh.Dial to see if this still hangs. If not, then there is some problem in Go, otherwise it is just ssh.Dial. Maybe you should also limit the number of simultanous goroutines using buffered channel. But I supose you would get an OS error in this case (using too much resources).
@Josh_Longhi’s code with go routine is actually too much for me to understand at first, so I created sshgo1.go with logic for only doing 1 host connection that works in my test lab. It has logging to show error message.
I am learning to finish sshgo2.go next by adding “for loop” .
And finally sshgo3.go with goroutine.
It seems that all my failed connections finish dealing and the program is hanging and now showing the two successful dials I expect. Could this be a channel issue?
@Josh_Longhi, Maybe you can add log.Fatal in goroutine section of code after this line " errors <- “Connection Failed " + host”, it will exit out and showing which host failed.
Again thanks for bring up this topic to encourage me to learn golang. hope we all got the idea ssh login check program we need.