go函数-死机:运行时错误:无效内存地址或零指针取消引用
提前感谢大家的帮助。我在第41、42和58行标记了问题发生的位置。我无法跟踪抛出错误的原因。似乎所有变量都已正确分配。我使用命令: go run file.go“命令”“ip地址”go函数-死机:运行时错误:无效内存地址或零指针取消引用,go,Go,提前感谢大家的帮助。我在第41、42和58行标记了问题发生的位置。我无法跟踪抛出错误的原因。似乎所有变量都已正确分配。我使用命令: go run file.go“命令”“ip地址” ex.-go run file.go正常运行时间8.8.8.8 错误是: panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1
ex.-go run file.go正常运行时间8.8.8.8 错误是:
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
主程序包
进口(
“字节”
“fmt”
“io/ioutil”
“日志”
“操作系统”
“时间”
“golang.org/x/crypto/ssh”
)
func main(){
cmd:=os.Args[1]
主机:=os.Args[2:]
结果:=制造(成串,10)
超时:=时间后(10*时间秒)
端口:=“22”
var hostKey ssh.PublicKey
key,err:=ioutil.ReadFile(“/home/user/file.pem”)
如果错误!=零{
log.Fatalf(“无法读取私钥:%v”,错误)
}
签名者,错误:=ssh.ParsePrivateKey(key)
如果错误!=零{
log.Fatalf(“无法分析私钥:%v”,错误)
}
config:=&ssh.ClientConfig{
用户:“ec2用户”,
Auth:[]ssh.AuthMethod{
ssh.PublicKeys(签名者),
},
HostKeyCallback:ssh.FixedHostKey(hostKey),
}
对于u,主机名:=范围主机{
go func(主机名字符串、端口字符串){//第41行
结果正如@JoshuaKolden指出的,您需要检查ssh.Dial产生的错误,如果值不是nil
,则不要继续。下面是带有错误检查的executeCmd
函数的一个版本:
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
}
当然,您还需要调整调用executeCmd
的goroutine以进行错误处理。可能需要将错误消息打印到os.Stderr
以找出问题所在
您感到恐慌的原因是,您从ssh.Dial
中出现了一个错误,将变量conn
的值保留为nil
。如果您查看ssh
包,您可以看到它对指针接收器c
进行方法调用,以OpenChannel
。通常这不是一个错误采用指针接收器的结构方法存在问题,但在本例中,OpenChannel
是嵌入在客户端
struct中的Conn
接口的方法。当使用nil接收器调用接口方法时,Go会崩溃
编辑:在goroutine中使用此新版本函数的一种可能方式:
go func(hostname string, port string) { // LINE 41
result, err := executeCmd(cmd, hostname, port, config) // LINE 42
if err != nil {
fmt.Fprintf(os.Stderr, "error running cmd on host %s port %s: %s", hostname, port, err)
return
}
results <- result
}(hostname, port)
go-func(主机名字符串、端口字符串){//第41行
结果,err:=executeCmd(cmd,主机名,端口,配置)//第42行
如果错误!=零{
fmt.Fprintf(os.Stderr,“在主机%s端口%s:%s上运行cmd时出错”,主机名,端口,错误)
返回
}
结果第一步是处理您在第57行忽略的错误。最有可能的conn
是nil
,返回的错误会告诉您原因。此外,您从未为hostKey
变量赋值,因此这也会咬到您,尽管会导致错误而不是恐慌。如果您希望隐式信任所有主机,使用unsecureIgnoreHostKey
而不是FixedHostKey
。感谢您的帮助。我将goroutine修改为err,results:=我已用如何使用它的示例更新了答案
go func(hostname string, port string) { // LINE 41
result, err := executeCmd(cmd, hostname, port, config) // LINE 42
if err != nil {
fmt.Fprintf(os.Stderr, "error running cmd on host %s port %s: %s", hostname, port, err)
return
}
results <- result
}(hostname, port)