Search in sources :

Example 1 with KillableObserver

use of com.google.copybara.shell.KillableObserver in project copybara by google.

the class CommandRunner method execute.

/**
 * Executes a {@link Command} with the given input and writes to the console and the log depending
 * on the exit code of the command and the verbose flag.
 */
public CommandOutputWithStatus execute() throws CommandException {
    Stopwatch stopwatch = Stopwatch.createStarted();
    String startMsg = ShellUtils.prettyPrintArgv(Arrays.asList(cmd.getCommandLineElements()));
    startMsg = startMsg.length() > MAX_COMMAND_LENGTH ? startMsg.substring(0, MAX_COMMAND_LENGTH) + "..." : startMsg;
    String validStartMsg = "Executing [" + startMsg + "]";
    logger.atInfo().log("%s", validStartMsg);
    if (verbose) {
        System.err.println(validStartMsg);
    }
    TerminationStatus exitStatus = null;
    CombinedKillableObserver cmdMonitor = new CombinedKillableObserver(timeout, additionalObservers.toArray(new KillableObserver[0]));
    ByteArrayOutputStream stdoutCollector = new ByteArrayOutputStream();
    ByteArrayOutputStream stderrCollector = new ByteArrayOutputStream();
    try {
        if (asyncStdoutStream.isPresent()) {
            stdoutCollector.write("stdOut redirected to external observer.".getBytes(UTF_8));
        }
        if (asyncErrStream.isPresent()) {
            stderrCollector.write("stdErr redirected to external observer.".getBytes(UTF_8));
        }
    } catch (IOException e) {
        logger.atSevere().withCause(e).log("Error writing output.");
    }
    OutputStream stdoutStream = commandOutputStream(asyncStdoutStream.orElse(stdoutCollector));
    OutputStream stderrStream = commandOutputStream(asyncErrStream.orElse(stderrCollector));
    try {
        CommandExecutor runner = executor.orElse(new DefaultExecutor());
        TerminationStatus status = runner.getCommandOutputWithStatus(cmd, input, cmdMonitor, stdoutStream, stderrStream);
        exitStatus = status;
        return new CommandOutputWithStatus(status, stdoutCollector.toByteArray(), stderrCollector.toByteArray());
    } catch (BadExitStatusException e) {
        exitStatus = e.getResult().getTerminationStatus();
        maybeTreatTimeout(stdoutCollector, stderrCollector, cmdMonitor, e);
        throw new BadExitStatusWithOutputException(e.getCommand(), e.getResult(), e.getMessage(), stdoutCollector.toByteArray(), stderrCollector.toByteArray());
    } catch (AbnormalTerminationException e) {
        maybeTreatTimeout(stdoutCollector, stderrCollector, cmdMonitor, e);
        throw e;
    } finally {
        String commandName = cmd.getCommandLineElements()[0];
        if (maxOutLogLines != 0) {
            logOutput(Level.INFO, String.format("'%s' STDOUT: ", commandName), stdoutCollector, maxOutLogLines);
            logOutput(Level.INFO, String.format("'%s' STDERR: ", commandName), stderrCollector, maxOutLogLines);
        }
        String finishMsg;
        if (cmdMonitor.hasTimedOut()) {
            finishMsg = String.format("Command '%s' was killed after timeout. Execution time %s. %s", commandName, formatDuration(stopwatch.elapsed()), exitStatus != null ? exitStatus.toString() : "(No exit status)");
            logger.atSevere().log("%s", finishMsg);
        } else {
            finishMsg = String.format("Command '%s' finished in %s. %s", commandName, formatDuration(stopwatch.elapsed()), exitStatus != null ? exitStatus.toString() : "(No exit status)");
            logger.atInfo().log("%s", finishMsg);
        }
        if (verbose) {
            System.err.println(finishMsg);
        }
    }
}
Also used : TimeoutKillableObserver(com.google.copybara.shell.TimeoutKillableObserver) KillableObserver(com.google.copybara.shell.KillableObserver) ByteArrayOutputStream(java.io.ByteArrayOutputStream) OutputStream(java.io.OutputStream) Stopwatch(com.google.common.base.Stopwatch) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) TerminationStatus(com.google.copybara.shell.TerminationStatus) AbnormalTerminationException(com.google.copybara.shell.AbnormalTerminationException) BadExitStatusException(com.google.copybara.shell.BadExitStatusException)

Example 2 with KillableObserver

use of com.google.copybara.shell.KillableObserver in project copybara by google.

the class CommandRunnerTest method testObserverCanTerminate.

@Test
public void testObserverCanTerminate() throws Exception {
    KillableObserver tester = new KillableObserver() {

        @Override
        public void startObserving(Killable killable) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {
            // ignored
            }
            killable.kill();
        }

        @Override
        public void stopObserving(Killable killable) {
        }
    };
    Command command = bashCommand("" + "echo stdout msg\n" + ">&2 echo stderr msg\n" + "sleep 10\n");
    AbnormalTerminationException e = assertThrows(AbnormalTerminationException.class, () -> runCommand(new CommandRunner(command, Duration.ofSeconds(90)).withObserver(tester)));
    assertThat(e).hasMessageThat().containsMatch("Process terminated by signal 15");
    assertThat(e).hasMessageThat().doesNotContainMatch("Command '.*' killed by Copybara after timeout \\(1s\\)");
}
Also used : KillableObserver(com.google.copybara.shell.KillableObserver) Command(com.google.copybara.shell.Command) Killable(com.google.copybara.shell.Killable) AbnormalTerminationException(com.google.copybara.shell.AbnormalTerminationException) CommandRunner(com.google.copybara.util.CommandRunner) Test(org.junit.Test)

Example 3 with KillableObserver

use of com.google.copybara.shell.KillableObserver in project copybara by google.

the class CommandRunnerTest method testCommandWithCustomRunner.

@Test
public void testCommandWithCustomRunner() throws Exception {
    Command command = bashCommand("");
    CommandException e = assertThrows(CommandException.class, () -> runCommand(new CommandRunner(command).withCommandExecutor(new CommandExecutor() {

        @Override
        public TerminationStatus getCommandOutputWithStatus(Command cmd, byte[] input, KillableObserver cmdMonitor, OutputStream stdoutStream, OutputStream stderrStream) throws CommandException {
            throw new CommandException(cmd, "OH NOES!");
        }
    })));
    assertThat(e).hasMessageThat().contains("OH NOES!");
}
Also used : Command(com.google.copybara.shell.Command) KillableObserver(com.google.copybara.shell.KillableObserver) TerminationStatus(com.google.copybara.shell.TerminationStatus) ByteArrayOutputStream(java.io.ByteArrayOutputStream) OutputStream(java.io.OutputStream) CommandExecutor(com.google.copybara.util.CommandRunner.CommandExecutor) CommandException(com.google.copybara.shell.CommandException) CommandRunner(com.google.copybara.util.CommandRunner) Test(org.junit.Test)

Aggregations

KillableObserver (com.google.copybara.shell.KillableObserver)3 AbnormalTerminationException (com.google.copybara.shell.AbnormalTerminationException)2 Command (com.google.copybara.shell.Command)2 TerminationStatus (com.google.copybara.shell.TerminationStatus)2 CommandRunner (com.google.copybara.util.CommandRunner)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 OutputStream (java.io.OutputStream)2 Test (org.junit.Test)2 Stopwatch (com.google.common.base.Stopwatch)1 BadExitStatusException (com.google.copybara.shell.BadExitStatusException)1 CommandException (com.google.copybara.shell.CommandException)1 Killable (com.google.copybara.shell.Killable)1 TimeoutKillableObserver (com.google.copybara.shell.TimeoutKillableObserver)1 CommandExecutor (com.google.copybara.util.CommandRunner.CommandExecutor)1 IOException (java.io.IOException)1