
首先需求是调用 ssh 访问腾讯云云实例执行 A 脚本,然后对此云实例进行重启,开机完成后再执行 B 脚本。从执行 A ,重启到开机都没有问题,但是在执行 B 脚本前新建 session 时,调用 client.NewSession()方法一直返回 error:EOF ,实在是定位不到问题,求大佬指教。
我的 ssh 连接逻辑抽取的方法:
func SSHConnect(host string) (*ssh.Client, error) { var ( addr string clientConfig *ssh.ClientConfig client *ssh.Client err error ) homePath, err := os.UserHomeDir() if err != nil { return nil, err } key, err := ioutil.ReadFile(path.Join(homePath, ".ssh", "id_rsa")) zap.L().Info("key", zap.String("path", path.Join(homePath, ".ssh", "id_rsa"))) if err != nil { return nil, err } signer, err := ssh.ParsePrivateKey(key) if err != nil { return nil, err } clientCOnfig= &ssh.ClientConfig{ User: "root", Auth: []ssh.AuthMethod{ ssh.PublicKeys(signer), }, Timeout: 30 * time.Second, HostKeyCallback: ssh.InsecureIgnoreHostKey(), } // connect to ssh addr = fmt.Sprintf("%s:%d", host, 22) if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil { //err = errors.Wrapf(err, "") return nil, err } return client, nil } 调用 ssh 执行脚本 A:
var connectShut *ssh.Client var sessionShut *ssh.Session connectShut, err = util.SSHConnect(*ip[0]) if err != nil { zap.L().Error("mysqlToggleWorker SSHConnect error", zap.Error(err), zap.Any("ip", *ip[0])) return err } sessionShut, err = connectShut.NewSession() if err != nil { zap.L().Error("mysqlToggleWorker NewSession error", zap.Error(err), zap.Any("ip", *ip[0])) return err } shCommand := "sh " + shPath output, err := sessionShut.CombinedOutput(shCommand) if err != nil { zap.L().Error("mysqlToggleWorker Run error", zap.Error(err), zap.Any("ip", *ip[0]), zap.Any("shCommand", shCommand), zap.String("result", string(output))) } err = sessionShut.Close() if err != nil || err != io.EOF { zap.L().Error("mysqlToggleWorker sessionShut.Close() error", zap.Error(err), zap.Any("ip", *ip[0])) } err = connectShut.Close() if err != nil { zap.L().Error("mysqlToggleWorker connectShut.Close() error", zap.Error(err), zap.Any("ip", *ip[0])) } 省略重启的过程,下面开始调用脚本 B:
var connectStart *ssh.Client var sessionStart *ssh.Session connectStart, err = util.SSHConnect(*ip[0]) sessionStart, err = connectStart.NewSession() if err != nil { zap.L().Error("mysqlToggleWorker DescribeInstancesStatus error", zap.Error(err), zap.Any("ip", *ip[0])) return err } 此时返回的 err 为:{"error": "EOF", "ip": "10.1.0.1"}
百思不得其解,求大佬指教~
1 xhd2015 2024-03-28 17:05:12 +08:00 via iPhone 第一个 err 没有 check ,不知道你这个 err 是谁返回的 |
2 79lawyer OP @xhd2015 sessionStart, err = connectStart.NewSession()是这一句,上面的 err 没有报错所以刚刚复制的时候删掉了,怕代码太长哈哈哈 |
3 zhuisui 2024-03-28 17:39:00 +08:00 EOF 错误,end of file ,怀疑是第二次连接重用了第一次的连接 第二次连接如果单独调用正常吗,正常的话大概就是这样 没用过 ssh.Dial |
4 2024-03-28 17:39:22 +08:00 是不是对端服务还没 ready 或者 TCP 状态不对。抓包看看,以及日志可以贴一下 如果没有明显问题,调试单步执行一下,看看是哪里报的错误 |
5 79lawyer OP @zhuisui 应该是这个问题,我把调用 ssh 和执行命令封装出来之后再调用就没有这个问题了,但是我第一次执行完正常 close 了呀,很奇怪 |
6 yann123 2024-03-28 17:47:37 +08:00 考虑过可能没有 id_rsa 文件吗 |
7 swulling 2024-03-28 17:52:02 +08:00 via iPhone 重启后你要等待 sshd 服务 ready ,不能在能 ping 通后马上去执行。 写一个 loop 吧,循环尝试 N 次执行一个命令比如 time 来探活,成功后再执行业务脚本。 其实你这个问题问 chatgpt 就会给你和我一样的建议。 |
8 zhuisui 2024-03-28 17:59:50 +08:00 如果是服务端侧的问题,应该是 connection close/reset/aborted 类错误 倒不如直接抓包,看看第二次调用是否真的建立了 tcp 连接 ------------ 如果觉得奇怪就还原之前的代码,用正确的和错误的来对比,具体哪个细节逻辑不一样 |