2020-12-09-使用ganymed-ssh2库连接linux服务器执行shell命令卡死猜想

问题现象:

                session = conn.openSession();  // 打开一个会话
                session.execCommand(cmd, DEFAULT_CHAR_SET);      // 执行命令

                StringBuilder builder = new StringBuilder();
                try {
                    br = new BufferedReader(new InputStreamReader(new StreamGobbler(session.getStdout()), "UTF-8"));
                    String line;

                    // 启动线程读取 error,防止 hang 住
                    //printStream(session.getStderr(), printWriterList);

                    while ((line = br.readLine()) != null) {
//                        writeLog(printWriterList, line);
                        //打印日志
                        if (line.contains("2 dependencies")) {
                            System.out.println("dead loop");
                        }
                        builder.append(line).append("\n");
                    }
                    session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);

                    // 获取执行的退出码
                    Integer status = session.getExitStatus();

                } catch (IOException e) {
                    System.err.println("解析脚本出错:" + e.getMessage());
                    e.printStackTrace();
                } finally {
                    if (session != null) {
                        session.close();
                    }
                }

上方代码 printStream(session.getStderr(), printWriterList); 注释掉了,当执行完命令后,在 while 循环中,会发生 readLine() hang 住的现象。

打开注释之后,先把 Stderr 流打印出来,就可以正常运行。

private static void printStream(InputStream inputStream, List<PrintWriter> printWriterList) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                InputStreamReader isr = null;
                BufferedReader br = null;
                try {
                    isr = new InputStreamReader(inputStream, "utf8");
                    br = new BufferedReader(isr);
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        writeLog(printWriterList, line);
                        // System.out.println(outtag + "" + line);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (br != null) {
                            br.close();
                        }
                        if (isr != null) {
                            isr.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

个人猜想:

ganymed-ssh2 库在建立ssh连接后,会创建一个 buffer 缓冲来存放服务器返回的数据流,包含 stdOutStream 和 stdErrStream 流,这两个 inputStream 是存放在同一个 buffer 中,当循环读取 stdOutStream 中的内容时,读完标准输出流之后,遇到标准错误流,由于 buffer 中同时存在 stdErrStream,此时由于标准错误流一直没有被读取,所以度标准输出流的 readLine() 就被hang 住。

主要原因:

stdOutStream 和 stdErrStream 流 共用同一个 buffer,当 errStream 写满了 buffer 之后,outStream 就无法再写入内容,造成 outStream hang 住。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值