LinuxCommandExecutor
Linux Command Executor
Utility class to run linux commands from java application
ProcessExecutor.java
package com.codergists.util;
import com.codergists.exception.ProcessExecutionException;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import static java.lang.String.join;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.logging.log4j.util.Strings.isEmpty;
/**
* ProcessExecutor to run list of commands and return success response.
* <p>
* This Singleton class executes array of commands on {@link Runtime} and wait for specified Time Period to get the
* response back.
* <p>
*
* @author tvajjala = ProcessExecutor.getInstance().execute("whoami");
*/
@Slf4j
public final class ProcessExecutor {
/**
* runtime
*/
private static final Runtime RUNTIME = Runtime.getRuntime();
/**
* process execution
*/
private static final ProcessExecutor _INSTANCE = new ProcessExecutor();
/**
* private constructor
*/
private ProcessExecutor() {
}
/**
* Return instance of {@link ProcessExecutor}
*
* @return CommandExecutor
*/
public static ProcessExecutor getInstance() {
return _INSTANCE;
}
/**
* Execute commands and return response with default TimeoutPeriod ( 3 seconds)
*
* @param commands arrays of commands to be executed
* @return success response as string
*/
public String execute(final String... commands) {
return execute(60L, commands);
}
/**
* Execute commands and return response with specific timeOutPeriod in seconds
*
* @param timeOutInSeconds timeOutInSeconds
* @param commands arrays of commands to be executed
* @return success response as string
*/
public String execute(final long timeOutInSeconds, final String... commands) {
Process process = null;
String command = join(" ", commands);//delimiter must be space.
try (ByteArrayOutputStream errorOutputStream = new ByteArrayOutputStream();
ByteArrayOutputStream successOutputStream = new ByteArrayOutputStream()) {
log.info("Executing command [{}]", command);
process = RUNTIME.exec(new String[] { "/bin/sh", "-c", command });
asyncStreamReader(process.getErrorStream(), errorOutputStream);
asyncStreamReader(process.getInputStream(), successOutputStream);
log.debug("Waiting process to be completed");
process.waitFor(timeOutInSeconds, SECONDS);
int exitCode = process.exitValue();
final String successResponse = new String(successOutputStream.toByteArray()).trim();
final String errorResponse = new String(errorOutputStream.toByteArray()).trim();
//FAILURE-CASE:exitCode=0, with errorResponse
if (!isEmpty(errorResponse)) {
log.warn("Received errorResponse {}", errorResponse);
throw new ProcessExecutionException(errorResponse, exitCode);
}
//FAILURE-CASE:exitCode!=0
if (exitCode != 0) {
String errorMsg = successResponse + errorResponse;
log.warn("Received exitCode {} with response {}", exitCode, errorMsg);
throw new ProcessExecutionException(errorMsg, exitCode);
}
//SUCCESS-CASE: for exitCode==0
log.info("Received successResponse {}", successResponse);
return successResponse;
} catch (final ProcessExecutionException processExecutionException) {
//don't log as error, caller will decide whether error or not
log.warn("Failed to execute command [{}]", command, processExecutionException);
throw processExecutionException;
} catch (final Exception unknownException) {
//don't log as error, caller will decide whether error or not
log.warn("Unknown exception while running command [{}]", command);
throw new ProcessExecutionException(unknownException.getMessage(), unknownException);
} finally {
try {
if (null != process) {
process.destroy();
}
log.debug("Process destroyed successfully");
} catch (final Exception processCloseException) {
log.warn("Failed to destroy the process", processCloseException);
}
}
}
private void asyncStreamReader(final InputStream inputStream, OutputStream outputStream) {
new Thread(() -> {
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {
String input;
while ((input = reader.readLine()) != null) {
writer.write(input);
writer.newLine();
writer.flush();
}
} catch (final IOException ioException) {
log.warn("Unable to read the stream", ioException);
throw new ProcessExecutionException("Unable to read the stream", ioException);
}
}).start();
}
}
Comments
Post a Comment