Thanks in advance for everyone's help. I've marked lines 41, 42, and 58 where the problem occurs. I have not been able to track what is throwing the error. It appears all the variables are properly assigned. I use the command:
go run file.go 'command' 'ip address'
ex. - go run file.go uptime 8.8.8.8
The error is:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x54fb36]
goroutine 20 [running]:
golang.org/x/crypto/ssh.(*Client).NewSession(0x0, 0x3, 0xc42009e310, 0x10)
/home/user/go/src/golang.org/x/crypto/ssh/client.go:130 +0x26
main.executeCmd(0x7ffce5f83a51, 0x6, 0x7ffce5f83a58, 0xd, 0x5d3077, 0x2, 0xc42009a820, 0x0, 0x0)
/home/user/ssh.go:58 +0x16f
main.main.func1(0xc4200d2000, 0x7ffce5f83a51, 0x6, 0xc42009a820, 0x7ffce5f83a58, 0xd, 0x5d3077, 0x2)
/home/user/ssh.go:42 +0x7a
created by main.main
/home/user/ssh.go:41 +0x41b
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"time"
"golang.org/x/crypto/ssh"
)
func main() {
cmd := os.Args[1]
hosts := os.Args[2:]
results := make(chan string, 10)
timeout := time.After(10 * time.Second)
port := "22"
var hostKey ssh.PublicKey
key, err := ioutil.ReadFile("/home/user/file.pem")
if err != nil {
log.Fatalf("unable to read private key: %v", err)
}
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
log.Fatalf("unable to parse private key: %v", err)
}
config := &ssh.ClientConfig{
User: "ec2-user",
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
HostKeyCallback: ssh.FixedHostKey(hostKey),
}
for _, hostname := range hosts {
go func(hostname string, port string) { // LINE 41
results <- executeCmd(cmd, hostname, port, config) // LINE 42
}(hostname, port)
}
for i := 0; i < len(hosts); i++ {
select {
case res := <-results:
fmt.Print(res)
case <-timeout:
fmt.Println("Timed out!")
return
}
}
}
func executeCmd(command, hostname string, port string, config *ssh.ClientConfig) (string, error) {
conn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", hostname, port), config)
if err != nil {
return "", err
}
defer conn.Close()
session, err := conn.NewSession() //LINE 58
if err != nil {
return "", err
}
defer session.Close()
var stdoutBuf bytes.Buffer
session.Stdout = &stdoutBuf
if err := session.Run(command); err != nil {
return "", err
}
return fmt.Sprintf("%s -> %s", hostname, stdoutBuf.String()), nil
}
connisnil, and the error returned would tell you why.hostKeyvariable and so that will bite you as well, albeit with an error instead of a panic. If you want to trust all hosts implicitly, useInsecureIgnoreHostKeyinstead ofFixedHostKey.