Class ProcessExecutor
It's implemented as a wrapper of ProcessBuilder
complementing it with additional features such as:
- Handling process streams (copied from Commons Exec library).
- Destroying process on VM exit (copied from Commons Exec library).
- Checking process exit code.
- Setting a timeout for running the process and automatically stopping it in case of timeout.
- Either waiting for the process to finish (
execute()
) or returning aFuture
(start()
. - Reading the process output stream into a buffer (
readOutput(boolean)
,ProcessResult
).
The default configuration for executing a process is following:
- Process is not automatically destroyed on VM exit.
- Error stream is redirected to its output stream. Use
redirectErrorStream(boolean)
to override it. - Output stream is pumped to a
NullOutputStream
, Usestreams(ExecuteStreamHandler)
,redirectOutput(OutputStream)
, or any of theredirectOutputAs*
methods.to override it. - Any exit code is allowed. Use
exitValues(Integer...)
to override it. - In case of timeout or cancellation
Process.destroy()
is invoked.
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionSet of accepted exit codes ornull
if all exit codes are allowed.private final ProcessBuilder
Process builder used by this executor.private Long
Timeout for closing process' standard streams.private TimeUnit
static final Integer[]
static final boolean
Environment variables which are added (removed in case ofnull
values) to the process being started.private static final boolean
private final CompositeProcessListener
Process event handlers.private static final org.slf4j.Logger
private MessageLogger
Helper for logging messages about starting and waiting for the processes.private static final Integer
private boolean
true
if the process output should be read to a buffer and returned byProcessResult.output()
.private ProcessStopper
Helper for stopping the process in case of timeout or cancellation.private ExecuteStreamHandler
Process stream Handler (copied from Commons Exec library).private Long
Timeout for running a process.private TimeUnit
-
Constructor Summary
ConstructorsConstructorDescriptionCreates newProcessExecutor
instance.ProcessExecutor
(Iterable<String> command) Creates newProcessExecutor
instance for the given program and its arguments.ProcessExecutor
(String... command) Creates newProcessExecutor
instance for the given program and its arguments.ProcessExecutor
(List<String> command) Creates newProcessExecutor
instance for the given program and its arguments. -
Method Summary
Modifier and TypeMethodDescriptionaddDestroyer
(ProcessDestroyer destroyer) Adds a process destroyer to be notified when the process starts and stops.addListener
(ProcessListener listener) Register new process event handler.private void
void
checkExitValue
(ProcessResult result) Check the exit value of given process result.Unregister all existing process event handlers.closeTimeout
(long timeout, TimeUnit unit) Sets a timeout for closing standard streams of the process being executed.Sets the program and its arguments which are being executed.Sets the program and its arguments which are being executed.Sets the program and its arguments which are being executed.commandSplit
(String commandWithArgs) Splits string by spaces and passes it tocommand(String...)
NB: this method do not handle whitespace escaping,"mkdir new\ folder"
would be interpreted as{"mkdir", "new\", "folder"}
command.debug()
Deprecated.Deprecated.debug
(org.slf4j.Logger log) Deprecated.destroyer
(ProcessDestroyer destroyer) Sets the process destroyer to be notified when the process starts and stops.Sets the started process to be destroyed on VM exit (shutdown hooks are executed).Sets this working directory for the process being executed.environment
(String name, String value) Adds a single additional environment variable for the process being executed.environment
(Map<String, String> env) Adds additional environment variables for the process being executed.execute()
Executes the sub process.Executes the sub process.Sets the allowed exit value for the process being executed.Allows any exit value for the process being executed.Allows only0
as the exit value for the process being executed.exitValues
(int[] exitValues) Sets the allowed exit values for the process being executed.exitValues
(Integer... exitValues) Sets the allowed exit values for the process being executed.fixArguments
(List<String> command) Fixes the command line arguments on Windows by replacing empty arguments with""
.private ProcessAttributes
Capture a snapshot of this process executor's main state.private org.slf4j.Logger
getCallerLogger
(String name) Creates aLogger
for theProcessExecutor
's caller class.Returns this process executor's operating system program and arguments.Returns this process executor's working directory.Returns this process executor's additional environment variables.private String
private String
private String
private static Integer
getExitCodeOrNull
(Process process) private static String
getUnitsAsString
(long d, TimeUnit unit) info()
Deprecated.Deprecated.info
(org.slf4j.Logger log) Deprecated.private Process
protected <T> Future
<T> invokeSubmit
(ExecutorService executor, Callable<T> task) Override this to customize how the waiting task is started in the background.listener
(ProcessListener listener) Unregister all existing process event handlers and register new one.protected ExecutorService
newExecutor
(String processName) private ExecutorService
newExecutor
(WaitForProcess task) private ProcessCloser
newProcessCloser
(ExecuteStreamHandler streams) private TimeoutException
newTimeoutException
(long timeout, TimeUnit unit, WaitForProcess task) pumps()
readOutput
(boolean readOutput) Sets this process executor'sreadOutput
property.redirectError
(OutputStream output) Redirects the process' error stream to given output stream.redirectErrorAlsoTo
(OutputStream output) Redirects the process' error stream also to a given output stream.private static PumpStreamHandler
redirectErrorAlsoTo
(PumpStreamHandler pumps, OutputStream output) Redirects the process' error stream also to a given output stream.Deprecated.redirectErrorAsDebug
(String name) Deprecated.redirectErrorAsDebug
(org.slf4j.Logger log) Deprecated.Deprecated.redirectErrorAsInfo
(String name) Deprecated.redirectErrorAsInfo
(org.slf4j.Logger log) Deprecated.redirectErrorStream
(boolean redirectErrorStream) Sets this process executor'sredirectErrorStream
property.redirectInput
(InputStream input) Sets the input stream to redirect to the process' input stream.redirectOutput
(OutputStream output) Redirects the process' output stream to given output stream.redirectOutputAlsoTo
(OutputStream output) Redirects the process' output stream also to a given output stream.private static PumpStreamHandler
redirectOutputAlsoTo
(PumpStreamHandler pumps, OutputStream output) Redirects the process' output stream also to a given output stream.Deprecated.redirectOutputAsDebug
(String name) Deprecated.redirectOutputAsDebug
(org.slf4j.Logger log) Deprecated.Deprecated.redirectOutputAsInfo
(String name) Deprecated.redirectOutputAsInfo
(org.slf4j.Logger log) Deprecated.removeListener
(ProcessListener listener) Unregister existing process event handler.removeListeners
(Class<? extends ProcessListener> listenerType) Unregister existing process event handlers of given type or its sub-types.setMessageLogger
(MessageLogger messageLogger) Changes how most common messages about starting and waiting for processes are actually logged.start()
Start the sub process.protected final WaitForProcess
Start the process and its stream handlers.private WaitForProcess
startInternal
(Process process, ProcessAttributes attributes, ExecuteStreamHandler streams, ByteArrayOutputStream out) stopper
(ProcessStopper stopper) Sets the helper for stopping the process in case of timeout or cancellation.streams()
streams
(ExecuteStreamHandler streams) Sets a stream handler for the process being executed.Sets a timeout for the process being executed.private void
validateStreams
(ExecuteStreamHandler streams, boolean readOutput) Validates that ifreadOutput
istrue
the output could be read with the givenExecuteStreamHandler
instance.private ProcessResult
waitFor
(WaitForProcess task) Wait until the process stops, a timeout occurs and the caller thread gets interrupted.protected <T> Callable
<T> Override this to customize how the background task is created.
-
Field Details
-
log
private static final org.slf4j.Logger log -
IS_OS_WINDOWS
private static final boolean IS_OS_WINDOWS -
DEFAULT_EXIT_VALUES
-
NORMAL_EXIT_VALUE
-
DEFAULT_REDIRECT_ERROR_STREAM
public static final boolean DEFAULT_REDIRECT_ERROR_STREAM- See Also:
-
builder
Process builder used by this executor. -
environment
Environment variables which are added (removed in case ofnull
values) to the process being started. -
allowedExitValues
Set of accepted exit codes ornull
if all exit codes are allowed. -
timeout
Timeout for running a process. If the process is running too long aTimeoutException
is thrown and the process is destroyed. -
timeoutUnit
-
stopper
Helper for stopping the process in case of timeout or cancellation. -
streams
Process stream Handler (copied from Commons Exec library). Ifnull
streams are not handled. -
closeTimeout
Timeout for closing process' standard streams. In case this timeout is reached we just log a warning but don't throw an error. -
closeTimeoutUnit
-
readOutput
private boolean readOutputtrue
if the process output should be read to a buffer and returned byProcessResult.output()
. -
listeners
Process event handlers. -
messageLogger
Helper for logging messages about starting and waiting for the processes.
-
-
Constructor Details
-
ProcessExecutor
public ProcessExecutor()Creates newProcessExecutor
instance. -
ProcessExecutor
Creates newProcessExecutor
instance for the given program and its arguments.- Parameters:
command
- The list containing the program and its arguments.
-
ProcessExecutor
Creates newProcessExecutor
instance for the given program and its arguments.- Parameters:
command
- A string array containing the program and its arguments.
-
ProcessExecutor
Creates newProcessExecutor
instance for the given program and its arguments.- Parameters:
command
- The iterable containing the program and its arguments.- Since:
- 1.8
-
-
Method Details
-
getCommand
Returns this process executor's operating system program and arguments. The returned list is a copy.- Returns:
- this process executor's program and its arguments (not
null
).
-
command
Sets the program and its arguments which are being executed.- Parameters:
command
- The list containing the program and its arguments.- Returns:
- This process executor.
-
command
Sets the program and its arguments which are being executed.- Parameters:
command
- A string array containing the program and its arguments.- Returns:
- This process executor.
-
command
Sets the program and its arguments which are being executed.- Parameters:
command
- The iterable containing the program and its arguments.- Returns:
- This process executor.
- Since:
- 1.8
-
commandSplit
Splits string by spaces and passes it tocommand(String...)
NB: this method do not handle whitespace escaping,"mkdir new\ folder"
would be interpreted as{"mkdir", "new\", "folder"}
command.- Parameters:
commandWithArgs
- A string array containing the program and its arguments.- Returns:
- This process executor.
-
getDirectory
Returns this process executor's working directory. Subprocesses subsequently started by this object will use this as their working directory. The returned value may benull
-- this means to use the working directory of the current Java process, usually the directory named by the system propertyuser.dir
, as the working directory of the child process.- Returns:
- this process executor's working directory
-
directory
Sets this working directory for the process being executed. The argument may benull
-- this means to use the working directory of the current Java process, usually the directory named by the system propertyuser.dir
, as the working directory of the child process.- Parameters:
directory
- The new working directory- Returns:
- This process executor.
-
getEnvironment
Returns this process executor's additional environment variables. The returned value is not a copy.- Returns:
- this process executor's environment variables (not
null
).
-
environment
Adds additional environment variables for the process being executed.- Parameters:
env
- environment variables added to the process being executed.- Returns:
- This process executor.
-
environment
Adds a single additional environment variable for the process being executed.- Parameters:
name
- name of the environment variable added to the process being executed.value
- value of the environment variable added to the process being executed.- Returns:
- This process executor.
- Since:
- 1.7
-
redirectErrorStream
Sets this process executor'sredirectErrorStream
property.If this property is
true
, then any error output generated by subprocesses will be merged with the standard output. This makes it easier to correlate error messages with the corresponding output. The initial value istrue
.- Parameters:
redirectErrorStream
- The new property value- Returns:
- This process executor.
-
exitValueAny
Allows any exit value for the process being executed.- Returns:
- This process executor.
-
exitValueNormal
Allows only0
as the exit value for the process being executed.- Returns:
- This process executor.
-
exitValue
Sets the allowed exit value for the process being executed.- Parameters:
exitValue
- single exit value ornull
if all exit values are allowed.- Returns:
- This process executor.
-
exitValues
Sets the allowed exit values for the process being executed.- Parameters:
exitValues
- set of exit values ornull
if all exit values are allowed.- Returns:
- This process executor.
-
exitValues
Sets the allowed exit values for the process being executed.- Parameters:
exitValues
- set of exit values ornull
if all exit values are allowed.- Returns:
- This process executor.
-
timeout
Sets a timeout for the process being executed. When this timeout is reached aTimeoutException
is thrown and the process is destroyed. This only applies toexecute
methods notstart
methods.- Parameters:
timeout
- timeout for running a process.unit
- the time unit of the timeout- Returns:
- This process executor.
-
stopper
Sets the helper for stopping the process in case of timeout or cancellation.By default
DestroyProcessStopper
is used which just invokesProcess.destroy()
.- Parameters:
stopper
- helper for stopping the process (null
meansNopProcessStopper
- process is not stopped).- Returns:
- This process executor.
-
streams
- Returns:
- current stream handler for the process being executed.
-
streams
Sets a stream handler for the process being executed. This will overwrite any stream redirection that was previously set to use the provided handler.- Parameters:
streams
- the stream handler- Returns:
- This process executor.
-
closeTimeout
Sets a timeout for closing standard streams of the process being executed. When this timeout is reached we log a warning but consider that the process has finished. We also flush the streams so that all output read so far is available.This can be used on Windows in case a process exits quickly but closing the streams blocks forever.
Closing timeout must fit into the general execution timeout (see
timeout(long, TimeUnit)
). By default there's no closing timeout.- Parameters:
timeout
- timeout for closing streams of a process.unit
- the time unit of the timeout- Returns:
- This process executor.
-
redirectInput
Sets the input stream to redirect to the process' input stream. If this method is invoked multiple times each call overwrites the previous.- Parameters:
input
- input stream that will be written to the process input stream (null
means nothing will be written to the process input stream).- Returns:
- This process executor.
-
redirectOutput
Redirects the process' output stream to given output stream. If this method is invoked multiple times each call overwrites the previous. UseredirectOutputAlsoTo(OutputStream)
if you want to redirect the output to multiple streams.- Parameters:
output
- output stream where the process output is redirected to (null
meansNullOutputStream
which acts like a/dev/null
).- Returns:
- This process executor.
-
redirectError
Redirects the process' error stream to given output stream. If this method is invoked multiple times each call overwrites the previous. UseredirectErrorAlsoTo(OutputStream)
if you want to redirect the error to multiple streams.Calling this method automatically disables merging the process error stream to its output stream.
- Parameters:
output
- output stream where the process error is redirected to (null
meansNullOutputStream
which acts like a/dev/null
).- Returns:
- This process executor.
-
redirectOutputAlsoTo
Redirects the process' output stream also to a given output stream. This method can be used to redirect output to multiple streams.- Parameters:
output
- the stream to redirect this output to- Returns:
- This process executor.
-
redirectErrorAlsoTo
Redirects the process' error stream also to a given output stream. This method can be used to redirect error to multiple streams.Calling this method automatically disables merging the process error stream to its output stream.
- Parameters:
output
- the output stream to redirect the error stream to- Returns:
- This process executor.
-
pumps
- Returns:
- current PumpStreamHandler (maybe
null
). - Throws:
IllegalStateException
- if the current stream handler is not an instance ofPumpStreamHandler
.- See Also:
-
redirectOutputAlsoTo
Redirects the process' output stream also to a given output stream.- Returns:
- new stream handler created.
-
redirectErrorAlsoTo
Redirects the process' error stream also to a given output stream.- Returns:
- new stream handler created.
-
readOutput
Sets this process executor'sreadOutput
property.If this property is
true
, the process output should be read to a buffer and returned byProcessResult.output()
. The initial value isfalse
.- Parameters:
readOutput
- The new property value- Returns:
- This process executor.
-
validateStreams
Validates that ifreadOutput
istrue
the output could be read with the givenExecuteStreamHandler
instance. -
info
Deprecated.Logs the process' output to a givenLogger
withinfo
level.- Parameters:
log
- the logger to process the output to- Returns:
- This process executor.
-
debug
Deprecated.Logs the process' output to a givenLogger
withdebug
level.- Parameters:
log
- the logger to process the output to- Returns:
- This process executor.
-
info
Deprecated.Logs the process' output to aLogger
with given name usinginfo
level.- Parameters:
name
- the name of the logger to process the output to- Returns:
- This process executor.
-
debug
Deprecated.Logs the process' output to aLogger
with given name usingdebug
level.- Parameters:
name
- the name of the logger to process the output to- Returns:
- This process executor.
-
info
Deprecated.Logs the process' output to aLogger
of the caller class usinginfo
level.- Returns:
- This process executor.
-
debug
Deprecated.Logs the process' output to aLogger
of the caller class usingdebug
level.- Returns:
- This process executor.
-
redirectOutputAsInfo
Deprecated.Logs the process' output to a givenLogger
withinfo
level.- Parameters:
log
- the logger to output the message to- Returns:
- This process executor.
-
redirectOutputAsDebug
Deprecated.Logs the process' output to a givenLogger
withdebug
level.- Parameters:
log
- the logger to output the message to- Returns:
- This process executor.
-
redirectOutputAsInfo
Deprecated.Logs the process' output to aLogger
with given name usinginfo
level.- Parameters:
name
- the name of the logger to log to- Returns:
- This process executor.
-
redirectOutputAsDebug
Deprecated.Logs the process' output to aLogger
with given name usingdebug
level.- Parameters:
name
- the name of the logger to process output to- Returns:
- This process executor.
-
redirectOutputAsInfo
Deprecated.Logs the process' output to aLogger
of the caller class usinginfo
level.- Returns:
- This process executor.
-
redirectOutputAsDebug
Deprecated.Logs the process' output to aLogger
of the caller class usingdebug
level.- Returns:
- This process executor.
-
redirectErrorAsInfo
Deprecated.Logs the process' error to a givenLogger
withinfo
level.- Parameters:
log
- the logger to process output to- Returns:
- This process executor.
-
redirectErrorAsDebug
Deprecated.Logs the process' error to a givenLogger
withdebug
level.- Parameters:
log
- the logger to process the error to- Returns:
- This process executor.
-
redirectErrorAsInfo
Deprecated.Logs the process' error to aLogger
with given name usinginfo
level.- Parameters:
name
- the name of the logger to process the error to- Returns:
- This process executor.
-
redirectErrorAsDebug
Deprecated.Logs the process' error to aLogger
with given name usingdebug
level.- Parameters:
name
- the name of the logger to process the error to- Returns:
- This process executor.
-
redirectErrorAsInfo
Deprecated.Logs the process' error to aLogger
of the caller class usinginfo
level.- Returns:
- This process executor.
-
redirectErrorAsDebug
Deprecated.Logs the process' error to aLogger
of the caller class usingdebug
level.- Returns:
- This process executor.
-
getCallerLogger
Creates aLogger
for theProcessExecutor
's caller class.- Parameters:
name
- name of the logger.- Returns:
- SLF4J Logger instance.
-
addDestroyer
Adds a process destroyer to be notified when the process starts and stops.- Parameters:
destroyer
- helper for destroying all processes on certain event such as VM exit (notnull
).- Returns:
- This process executor.
-
destroyer
Sets the process destroyer to be notified when the process starts and stops.This methods always removes any other
ProcessDestroyer
registered. UseaddDestroyer(ProcessDestroyer)
to keep the existing ones.- Parameters:
destroyer
- helper for destroying all processes on certain event such as VM exit (maybenull
).- Returns:
- This process executor.
-
destroyOnExit
Sets the started process to be destroyed on VM exit (shutdown hooks are executed). If this VM gets killed the started process may not get destroyed.To undo this command call
destroyer(null)
.- Returns:
- This process executor.
-
listener
Unregister all existing process event handlers and register new one.- Parameters:
listener
- process event handler to be set (maybenull
).- Returns:
- This process executor.
-
addListener
Register new process event handler.- Parameters:
listener
- process event handler to be added.- Returns:
- This process executor.
-
removeListener
Unregister existing process event handler.- Parameters:
listener
- process event handler to be removed.- Returns:
- This process executor.
-
removeListeners
Unregister existing process event handlers of given type or its sub-types.- Parameters:
listenerType
- process event handler type.- Returns:
- This process executor.
-
clearListeners
Unregister all existing process event handlers.- Returns:
- This process executor.
-
setMessageLogger
Changes how most common messages about starting and waiting for processes are actually logged. By defaultMessageLoggers.DEBUG
is used. However if someone is executing a process every secondMessageLoggers.TRACE
may be used e.g.- Parameters:
messageLogger
- message logger for certain level.- Returns:
- This process executor.
-
execute
public ProcessResult execute() throws IOException, InterruptedException, TimeoutException, InvalidExitValueExceptionExecutes the sub process. This method waits until the process exits, a timeout occurs or the caller thread gets interrupted. In the latter cases the process gets destroyed as well.- Returns:
- exit code of the finished process.
- Throws:
IOException
- an error occurred when process was started or stopped.InterruptedException
- this thread was interrupted.TimeoutException
- timeout set bytimeout(long, TimeUnit)
was reached.InvalidExitValueException
- if invalid exit value was returned (@seeexitValues(Integer...)
).
-
executeNoTimeout
public ProcessResult executeNoTimeout() throws IOException, InterruptedException, InvalidExitValueExceptionExecutes the sub process. This method waits until the process exits. Value passed totimeout(long, TimeUnit)
is ignored (useexecute()
for timeout).- Returns:
- exit code of the finished process.
- Throws:
IOException
- an error occurred when process was started or stopped.InterruptedException
- this thread was interrupted.InvalidExitValueException
- if invalid exit value was returned (@seeexitValues(Integer...)
).
-
checkExitValue
Check the exit value of given process result. This can be used by unit tests.- Parameters:
result
- process result which maybe constructed by a unit test.- Throws:
InvalidExitValueException
- if the given exit value was rejected.
-
start
Start the sub process. This method does not wait until the process exits. Value passed totimeout(long, TimeUnit)
is ignored. UseFuture.get()
to wait for the process to finish. Invokefuture.cancel(true);
to destroy the process.- Returns:
- Future representing the exit value of the finished process.
- Throws:
IOException
- an error occurred when process was started.
-
startInternal
Start the process and its stream handlers.- Returns:
- process the started process.
- Throws:
IOException
- the process or its stream handlers couldn't start (in the latter case we also destroy the process).
-
getAttributes
Capture a snapshot of this process executor's main state. -
invokeStart
- Throws:
IOException
-
getExecutingLogMessage
-
getExecutingErrorMessage
-
getExecutingMessageParams
-
startInternal
private WaitForProcess startInternal(Process process, ProcessAttributes attributes, ExecuteStreamHandler streams, ByteArrayOutputStream out) throws IOException - Throws:
IOException
-
newProcessCloser
-
waitFor
private ProcessResult waitFor(WaitForProcess task) throws IOException, InterruptedException, TimeoutException Wait until the process stops, a timeout occurs and the caller thread gets interrupted. In the latter cases the process gets destroyed as well. -
newExecutor
-
newExecutor
-
invokeSubmit
Override this to customize how the waiting task is started in the background.- Type Parameters:
T
- the type of the task- Parameters:
executor
- the executor service to submit the task ontask
- the task to be submitted- Returns:
- the future of the task
-
wrapTask
Override this to customize how the background task is created.- Type Parameters:
T
- the type of the Task- Parameters:
task
- the Task to be wrapped- Returns:
- the wrapped task
-
newTimeoutException
-
getUnitsAsString
-
getExitCodeOrNull
-
applyEnvironment
private void applyEnvironment() -
fixArguments
Fixes the command line arguments on Windows by replacing empty arguments with""
. Otherwise these arguments would be just skipped.
-
redirectOutput(OutputStream)
andSlf4jStream