【问题标题】:JSch channel.disconnect prevent logs from printingJSch channel.disconnect 防止打印日志
【发布时间】:2013-12-12 07:11:53
【问题描述】:

我正在使用 JSch 在远程机器上运行 shell 脚本,并使用 JSch 通道在我的日志文件中打印命令日志。问题是当脚本结束时,我做了一个 channel.disconnect 并且在断开连接后不久, System.out 停止打印到日志文件中。代码如下:

private int runShellScript(HashMap bundleDetails) {
        int exitStatus = -1;
        Channel channel = null;
        Session session = null;
        try {
            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");

            String host = (String) bundleDetails.get("host");
            String userName = (String) bundleDetails.get("userName");
            String password = (String) bundleDetails.get("password");
            String bundleName = findFileName((String) bundleDetails.get("bundleName"));

            String sourceLocation = (String) bundleDetails.get("sourceLocation");
            String logFileName = findFileName((String) bundleDetails.get("logFileName"));

            String targetLocation = (String)bundleDetails.get("targetLocation");            

            String command1 = "sh "+(String) bundleDetails.get("targetIndexerLocation") + (String) bundleDetails.get("deployScript")+" "+
                                    targetLocation + bundleName + " " +
                                    targetLocation + logFileName;
            JSch ssh = new JSch();
            session = ssh.getSession(userName, host, 22);
            session.setConfig(config);
            session.setPassword(password);
            session.connect();

            channel = session.openChannel("exec");
            ((ChannelExec)channel).setCommand(command1);
            channel.setInputStream(null);
            ((ChannelExec)channel).setErrStream(System.err);
            InputStream in=channel.getInputStream();
            channel.connect();
            byte[] tmp=new byte[1024];
            while(true){
                //System.out.println("inside while second");
                  while(in.available()>0){
                    int i=in.read(tmp, 0, 1024);
                    if(i<0)break;
                    System.out.print("*****NEW ONE*****$$$$$**$$########"+new String(tmp, 0, i));
              }
                  if(channel.isClosed()){
                      exitStatus = channel.getExitStatus();
                     System.out.println("Before Disconnected Here exit-status: "+exitStatus);
                      channel.disconnect();
                    System.out.println("Disconnected Here exit-status: "+exitStatus);
                    break;
                  }
            }       
            //logger("runShellScript", "END");
            System.out.println("***** out of infinite loop");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Copy to remote location failed.... ");
        }finally{
            System.out.println("finally DISCONNECT channel and session");
            if(channel!=null && channel.isConnected()){
                channel.disconnect();
            }
            if(session!=null){
                session.disconnect();
            }           
            System.out.println("finally DISCONNECTED channel and session");

        }
        System.out.println("Before return exit-status: "+exitStatus);
        return exitStatus;
    }

日志文件中的行:

*****NEW ONE*****$$$$$**$$########Starting... 

在此处断开连接之前退出状态:0

如果您在我上面粘贴的方法中看到,打印的 sysout 实际上是 'channel.disconnect' 上方的那个。它下面的没有打印!所有的功能都是正确的,整体输出是我所期望的

System.out.println("此处断开前退出状态: "+exitStatus);
channel.disconnect();
System.out.println("断开连接 这里 exit-status: "+exitStatus);

所有功能都是正确的,整体输出符合我的预期。唯一的问题是日志冻结。我哪里错了?

编辑
另外,我无法从 finally 块中看到 syouts!

【问题讨论】:

    标签: java ssh jsch


    【解决方案1】:

    这是因为

    ((ChannelExec)channel).setErrStream(System.err);
    

    当你断开通道时,连接的流也被断开。

    所以请在断开频道前写下以下语句:

    ((ChannelExec)channel).setErrStream(null);
    

    【讨论】:

      【解决方案2】:

      很可能与这一行有关:

      ((ChannelExec)channel).setErrStream(System.err);
      

      通过这样做,您已将 System.err 流绑定到通道流。根据文档,默认情况下,当通道断开连接时,流会关闭。你没有说你在哪个平台上运行,但我认为大多数平台都以某种方式连接 System.err 和 System.out,所以 Jsch 很可能在断开连接时关闭 System.out。您可以尝试这样做以防止 JSch 关闭流:

      ((ChannelExec)channel).setErrStream(System.err, true);
      

      Javadoc

      即使这确实有效,我认为像这样连接到 System.err 也有点冒险。我认为更安全的设计是创建一个直接写入日志文件的流,而不是通过 System.err。

      【讨论】:

      • 哇!!完美地工作。噗,我错过了。非常感谢 kaliatech 的快速响应。一定会应用你的建议!
      猜你喜欢
      • 2022-01-11
      • 1970-01-01
      • 2015-09-17
      • 1970-01-01
      • 2016-04-28
      • 2016-03-22
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多