private BuildFinishedStatus executeCommand()

in deploy-runner-agent/src/main/java/jetbrains/buildServer/deployer/agent/ssh/SSHExecProcessAdapter.java [73:156]


  private BuildFinishedStatus executeCommand(Session session, String pty, String command) throws JSchException {
    ChannelExec channel = null;
    BuildFinishedStatus result = BuildFinishedStatus.FINISHED_SUCCESS;
    myLogger.message("Executing commands:\n" + command + "\non host [" + session.getHost() + "]");
    try {
      channel = (ChannelExec) session.openChannel("exec");
      if (!StringUtil.isEmpty(pty)) {
        channel.setPty(true);
        channel.setPtyType(pty);
      }

      channel.setAgentForwarding(myOptions.enableSshAgentForwarding());
      channel.setCommand(command);
      final AtomicLong lastOutputTimeStamp = new AtomicLong(System.currentTimeMillis());

      final LineAwareByteArrayOutputStream.LineListener lineListener = new LineAwareByteArrayOutputStream.LineListener() {
        @Override
        public void newLineDetected(@NotNull String line) {
          myLogger.message(line);
          lastOutputTimeStamp.set(System.currentTimeMillis());
        }
      };
      final LineAwareByteArrayOutputStream outputStream = new LineAwareByteArrayOutputStream(Charset.forName("UTF-8"), lineListener);
      final StreamGobbler outputGobbler = new StreamGobbler(channel.getInputStream(), null, "SSH session to [" + session.getHost() + "]", outputStream);
      final LineAwareByteArrayOutputStream errStream = new LineAwareByteArrayOutputStream(Charset.forName("UTF-8"), lineListener);
      final StreamGobbler errGobbler = new StreamGobbler(channel.getErrStream(), null, "Unknown", errStream);

      outputGobbler.start();
      errGobbler.start();
      channel.connect(CONNECTION_OPEN_TIMEOUT_MS);

      while (!isInterrupted()
          && channel.isConnected()
          && !channel.isEOF()
          && !channel.isClosed()) {

        try {
          Thread.sleep(500);
          // sometimes no newline chars are present, but still some output may be pending
          final boolean hasSomePendingOutput = outputGobbler.getLastActivityTimestamp() > lastOutputTimeStamp.get();
          final boolean waitingForTooLong = System.currentTimeMillis() - outputGobbler.getLastActivityTimestamp() > CONNECTION_SILENCE_THRESHOLD_MS;
          if (waitingForTooLong && hasSomePendingOutput) {
            // force dump of current pending output
            outputStream.write("\n".getBytes(Charset.forName("UTF-8")));
          }
        } catch (InterruptedException e) {
          checkIsInterrupted();
        }
      }

      outputGobbler.notifyProcessExit();
      errGobbler.notifyProcessExit();
      try {
        outputGobbler.join();
        errGobbler.join();
      } catch (InterruptedException e) {
        LOG.warnAndDebugDetails("SSH command interrupted", e);
      }

      if (isInterrupted()) {
        myLogger.message("Interrupted.");
      }
    } catch (IOException e) {
      myLogger.error(e.toString());
      LOG.warnAndDebugDetails(e.getMessage(), e);
      result = BuildFinishedStatus.FINISHED_FAILED;
    } finally {
      if (channel != null) {
        channel.disconnect();
        int exitCode = channel.getExitStatus();
        if (exitCode != 0) {
          if (myOptions.shouldFailBuildOnExitCode()) {
            logExitCodeBuildProblem(exitCode);
            result = BuildFinishedStatus.FINISHED_WITH_PROBLEMS;
          } else {
            logBuildProblem(myLogger, "SSH exit-code [" + exitCode + "]");
          }
        } else {
          myLogger.message("SSH exit-code [" + exitCode + "]");
        }
      }
    }
    return result;
  }