【问题标题】:Randomly getting empty output while executing shell command via JSch通过JSch执行shell命令时随机获取空输出
【发布时间】:2016-10-21 08:39:25
【问题描述】:

我正在尝试使用 JSch 通过 JSch(空间检查命令)执行以下 Linux 命令:

df -h -P |awk '{print $6"  "$4}' |awk '{ if ($1 == "/On_Demand") {print}}' | awk '{print $2}' | awk '{ if ($1 ~ /M/) {print ($1*1)} else if($1 ~ /G/) {print ($1*1024)} else if($1 ~ /T/) {print ($1*1024*1024)} else if($1==0) {print ($1*1)} else if($1 ~ /K/) {print ($1/1024)} else {print ("-1")}}'

备份命令:

export ORACLE_HOME=/path/to/ora/home;export ORACLE_SID=sid;/U01/NEW_DEMO/path/to/ora/home/bin/expdp username/password directory=ON_DEMAND schemas=xyz dumpfile=expdp_xyz.dmp logfile=xyz.log;tail -n 1 /On_Demand/xyz.log

读取输出的代码:

public String getOutput() {
    LOGGER.debug("[getOutput]");
    StringBuffer output = new StringBuffer();
    InputStream in = null;
    if (channel != null && channel.isConnected()) {
        try {
            in = channel.getInputStream();
            byte[] tmp = new byte[1024];
            while (true) {
                while (in.available() > 0) {
                    int i = in.read(tmp, 0, 1024);
                    if (i < 0)
                        break;
                    output.append(new String(tmp, 0, i));
                }
                if (channel.isClosed()) {
                    LOGGER.debug("[getOutput] Channel is closed, so breaking while loop with exit code: "+channel.getExitStatus());
                    break;
                }
            }
        } catch (IOException e) {
            LOGGER.error(e.toString());
            e.printStackTrace();
        } finally {
            channel.disconnect();
        }
    } else {
        System.out.println("Channel is disconnected");
    }

    return output.toString();
}

问题是,当我尝试读取命令输出时,很多时候我都获得了可用空间,但有时却没有输出。
当再次调用 SSH 类(如 2 或 3 次,在新会话中建立)以触发相同的命令时,我得到输出(这很奇怪)。

同样的问题发生在另一个功能中,我触发命令备份 Oracle 架构,当我尝试读取 Oracle 生成的日志文件时(同时触发备份和尾命令,分号分隔) ,我没有输出,但日志文件在那里。多次尝试触发相同的备份命令给了我输出。

这是一个月以来我的工具出现的一个大问题。

对此的任何帮助将不胜感激。

提前致谢。

【问题讨论】:

    标签: java ssh jsch


    【解决方案1】:

    我相信您的代码中有竞争条件。

    通道运行它自己的线程来读取数据。在您测试in.available() 之后,但在您测试channel.isConnected() 之前,线程可以接收数据。虽然相似度可能很低,但它完美地解释了您遇到的随机行为。

    查看official Exec.java example 如何在channel.isClosed() 块中再次重新测试in.available()

    byte[] tmp=new byte[1024];
    while(true){
      while(in.available()>0){
        int i=in.read(tmp, 0, 1024);
        if(i<0)break;
        System.out.print(new String(tmp, 0, i));
      }
      if(channel.isClosed()){
        if(in.available()>0) continue; 
        System.out.println("exit-status: "+channel.getExitStatus());
        break;
      }
      try{Thread.sleep(1000);}catch(Exception ee){}
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-15
      • 2013-07-30
      • 1970-01-01
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      • 2015-09-05
      • 1970-01-01
      相关资源
      最近更新 更多