public void start() { List<String> command = null; try { command = buildCommand(); } catch (InvalidShellCommandException isce) { shellCommandUpdater.sendUpdate(UpdateType.INVALID, Optional.of(isce.getMessage()), Optional.<String>absent()); return; } final String outputFilename = executorConfiguration.getShellCommandOutFile() .replace("{NAME}", shellRequest.getShellCommand().getLogfileName().or(convertCommandNameToLogfileName(shellRequest.getShellCommand().getName()))) .replace("{TIMESTAMP}", Long.toString(shellRequest.getTimestamp())); shellCommandUpdater.sendUpdate(UpdateType.ACKED, Optional.of(Joiner.on(" ").join(command)), Optional.of(outputFilename)); final File outputFile = MesosUtils.getTaskDirectoryPath(getTask().getTaskId()).resolve(outputFilename).toFile(); Map<String, String> additionalEnv = new HashMap<>(); additionalEnv.put("TASK_SANDBOX_DIR", MesosUtils.getTaskDirectoryPath(getTask().getTaskId()).toString()); SingularityExecutorShellCommandRunnerCallable callable = new SingularityExecutorShellCommandRunnerCallable(task.getLog(), shellCommandUpdater, buildProcessBuilder(command, outputFile, additionalEnv), outputFile); ListenableFuture<Integer> shellFuture = shellCommandExecutorService.submit(callable); Futures.addCallback(shellFuture, new FutureCallback<Integer>() { @Override public void onSuccess(Integer result) { task.getLog().info("ShellRequest {} finished with {}", shellRequest, result); shellCommandUpdater.sendUpdate(UpdateType.FINISHED, Optional.of(String.format("Finished with code %s", result)), Optional.<String>absent()); } @Override public void onFailure(Throwable t) { task.getLog().warn("ShellRequest {} failed", shellRequest, t); shellCommandUpdater.sendUpdate(UpdateType.FAILED, Optional.of(String.format("Failed - %s (%s)", t.getClass().getSimpleName(), t.getMessage())), Optional.<String>absent()); } }); }