【发布时间】:2015-09-23 20:17:29
【问题描述】:
我正在编写一个小工具,用于在许多不同的主机上并行执行命令。所有主机都可以使用相同的私钥登录。所以,我想使用 SSHAgent 来获取身份验证登录。当我将它用于单个主机时,它运行良好。但是当我在许多 goroutines 中使用它时,它就不起作用了。我很困惑,有人可以帮助我吗?非常感谢。 使用sshagent的代码如下:
func ExcuteRemote(uname,host,cmd string) (bool,error) {
ip,err := GetIp(host)
if err != nil {
fmt.Println(err)
return false,err
}
auths := []ssh.AuthMethod{}
if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
fmt.Println("get sock")
auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers))
defer sshAgent.Close()
}
config := &ssh.ClientConfig{
User: uname,
Auth: auths,
}
fmt.Println("after config")
client, err := ssh.Dial("tcp", ip+":"+"22", config)
if err != nil {
fmt.Println("something wrong when dial")
fmt.Println(err)
return false,err
}
session, err := client.NewSession()
if err != nil {
return false,err
}
defer session.Close()
var b bytes.Buffer
session.Stdout = &b
err = session.Run(cmd)
if err != nil {
return false,err
}
fmt.Println(b.String())
return true,nil
}
使用的频道代码如下:
func testchannel(ch chan int, uname,host,cmd string) error{
result,err := ExcuteRemote(uname,host,cmd)
if result {
fmt.Println(host + " ok")
} else {
fmt.Println(err)
fmt.Println(host + " failed")
}
ch <- 1
return nil
}
主要:
if *list != "" {
runtime.GOMAXPROCS(runtime.NumCPU())
hosts,err := ReadLine(*list)
if nil != err {
panic(err.Error())
}
chs := make([]chan int, len(hosts))
for index := 0; index < len(hosts); index++ {
chs[index] = make(chan int)
go testchannel(chs[index],uname,hosts[index],*cmd)
}
for _, ch := range(chs) {
<-ch
}
}
这样的恐慌:
panic: unreachable
goroutine 5 [running]:
golang.org/x/crypto/ssh/agent.(*client).Sign(0xc20801e440, 0x7f053381a9f8, 0xc208094100, 0xc208121b00, 0x201, 0x240, 0xc2080a6009, 0x0, 0x0)
/usr/local/gosrc/src/golang.org/x/crypto/ssh/agent/client.go:342 +0x472
golang.org/x/crypto/ssh/agent.(*agentKeyringSigner).Sign(0xc20801e560, 0x7f053380fb38, 0xc20803c2d0, 0xc208121b00, 0x201, 0x240, 0xe, 0x0, 0x0)
/usr/local/gosrc/src/golang.org/x/crypto/ssh/agent/client.go:562 +0x71
golang.org/x/crypto/ssh.publicKeyCallback.auth(0xc20801e480, 0xc2080a4040, 0x14, 0x20, 0xc20802a954, 0x4, 0x7f053381a998, 0xc2080ca000, 0x7f053380fb38, 0xc20803c2d0, ...)
/usr/local/gosrc/src/golang.org/x/crypto/ssh/client_auth.go:210 +0x5ee
golang.org/x/crypto/ssh.(*connection).clientAuthenticate(0xc2080b8080, 0xc2080b2000, 0x0, 0x0)
/usr/local/gosrc/src/golang.org/x/crypto/ssh/client_auth.go:34 +0x4e3
golang.org/x/crypto/ssh.(*connection).clientHandshake(0xc2080b8080, 0xc20801e4c0, 0x11, 0xc2080b2000, 0x0, 0x0)
/usr/local/gosrc/src/golang.org/x/crypto/ssh/client.go:112 +0x62e
golang.org/x/crypto/ssh.NewClientConn(0x7f05338111e8, 0xc2080aa000, 0xc20801e4c0, 0x11, 0xc2080420a0, 0x0, 0x0, 0x0, 0x41be71, 0x0, ...)
/usr/local/gosrc/src/golang.org/x/crypto/ssh/client.go:74 +0x140
golang.org/x/crypto/ssh.Dial(0x785a50, 0x3, 0xc20801e4c0, 0x11, 0xc2080420a0, 0x11, 0x0, 0x0)
/usr/local/gosrc/src/golang.org/x/crypto/ssh/client.go:176 +0xf9
main.ExcuteRemote(0xc20802a954, 0x4, 0xc20802a9a0, 0xe, 0x7fffa171b7fd, 0x6, 0xc200000000, 0x0, 0x0)
/home/myname/easyssh/r.go:126 +0x83f
main.testchannel(0xc208036120, 0xc20802a954, 0x4, 0xc20802a9a0, 0xe, 0x7fffa171b7fd, 0x6, 0x0, 0x0)
/home/myname/easyssh/r.go:217 +0x8c
created by main.main
/home/myname/gocode/easyssh/r.go:262 +0x638
【问题讨论】:
-
恐慌追踪中是否有任何迹象表明恐慌发生在哪里?
-
对不起,我忘了粘贴恐慌。我要粘贴它。
-
ssh.Dial() 出现恐慌
-
那个“无法到达”的行不应该发生。代理响应可能因并发使用而损坏,但我不确定在哪里。用比赛检测器试试这个(你可以将 GOMAXPROCS>1 设置为很好的衡量标准)。
-
我设置了 GOMAXPROCS 是这样的:runtime.GOMAXPROCS(runtime.NumCPU()),我的 NumCPU 是 8,也不好用