在goroutine里并发调用sshagent出现panic的解决方案
来源:互联网 发布:k均值聚类算法opencv 编辑:程序博客网 时间:2024/06/04 11:39
之前在做一个批量处理工具的时候遇到一个棘手的问题,好几天都没有解决,把问题发到了stackoverflow,但是也没有得到一个好的回复,后来自己解决并回答了这个问题。问题地址:http://stackoverflow.com/questions/30722304/golang-goroutine-use-sshagent-auth-not-work-well-and-throw-some-unexpect-panic
在使用goroutine实现并发登陆设备时,多个goroutine同时调用sshagent就出现了如下错误:
panic: unreachablegoroutine 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 +0x472golang.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 +0x71golang.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 +0x5eegolang.org/x/crypto/ssh.(*connection).clientAuthenticate(0xc2080b8080, 0xc2080b2000, 0x0, 0x0) /usr/local/gosrc/src/golang.org/x/crypto/ssh/client_auth.go:34 +0x4e3golang.org/x/crypto/ssh.(*connection).clientHandshake(0xc2080b8080, 0xc20801e4c0, 0x11, 0xc2080b2000, 0x0, 0x0) /usr/local/gosrc/src/golang.org/x/crypto/ssh/client.go:112 +0x62egolang.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 +0x140golang.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 +0xf9main.ExcuteRemote(0xc20802a954, 0x4, 0xc20802a9a0, 0xe, 0x7fffa171b7fd, 0x6, 0xc200000000, 0x0, 0x0) /home/myname/easyssh/r.go:126 +0x83fmain.testchannel(0xc208036120, 0xc20802a954, 0x4, 0xc20802a9a0, 0xe, 0x7fffa171b7fd, 0x6, 0x0, 0x0) /home/myname/easyssh/r.go:217 +0x8ccreated by main.main /home/myname/gocode/easyssh/r.go:262 +0x638
每个goroutine里面执行的内容如下: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}
获取认证如下(main函数里面):
var config *ssh.ClientConfig if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { config = GetConfig(uname,sshAgent) defer sshAgent.Close() } else { panic(err) }
向每个goroutine里面传递参数config,goroutine执行的函数如下:func RunInChannel(ch chan int, host,cmd string,config *ssh.ClientConfig) error{ result,_ := ExcuteRemote(host,cmd,config) if result { //do something } else { ret,err := ExcuteRemote(host,cmd,config) if ret { //do something } else { fmt.Println(err) } } ch <- 1 return nil}
0 0
- 在goroutine里并发调用sshagent出现panic的解决方案
- 理解 goroutine 的并发
- go的并发机制goroutine
- go的并发编程goroutine
- golang 里goroutine产生的线程数量
- 为什么我认为goroutine和channel是把别的平台上类库的功能内置在语言里
- 并发协程goroutine
- golang-并发编程goroutine
- android 内核出现kernel panic的分析OoPS panic
- 【Android解决方案】在onResume里调用getIntent()得到的是上一次数据
- 对于golang的goroutine并发处理任务时的理解
- GoLang之并发并行与goroutine的思考
- 挂载文件系统出现"kernel panic..." 史上最全解决方案
- 挂载文件系统出现"kernel panic..." 史上最全解决方案
- weblogic8.1部署的java项目在调用webservice时出现找不到方法的解决方案
- 在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案
- PJSIP在线程中调用出现提示注册线程pj_thread_register的解决方案
- 最近在调用 calendar.js 的时候出现中文乱码! 解决方案
- RTT学习笔记之内存池管理(静态内存池)
- [每天读书半小时] 2015-6-12 Servlet / JSP
- 不用加减乘除做加法
- 【java基础】——java面向对象(上)—面向对象、类与对象、封装、构造函数等
- 第一章:OGG简介
- 在goroutine里并发调用sshagent出现panic的解决方案
- GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助
- 小谈==与isEqual方法
- 最大堆,最小堆插入/删除以及最大堆的排序
- NativeViewer for VS2010
- 进一步改进小游戏
- 多角度思考 创造性思维 几乎整个Byteland王国都被森林和河流所覆盖 题
- 解压缩zip文件
- Git-删除本地目录的repository(本地仓库)