- Type Parameters:
O- the output type
- All Superinterfaces:
PipelineBuilder<O>
- All Known Subinterfaces:
ProcessBuilder.Input<O>
The overall process follows this state diagram:
Problems with the JDK ProcessBuilder
The JDK provides an interface to create and reap processes, which this API is based on.
This API contains all of the pieces necessary to perform this function.
However, there are many unstated requirements and caveats when using this API:
- All I/O has to be performed in separate, individual threads to avoid various deadlocks
- The ordering of process waiting and I/O is tricky to manage
- Processes may need to be cleaned up on JDK exit
- Error and output can be tricky to capture when they also need to be processed
Running processes
Trivial process execution can be initiated using theexec(...) and
execToString(...) methods.
To configure and create a single process beyond trivial cases,
the full builder API must be used.
The builder API is used by calling newBuilder(...),
chaining additional calls from the result of that method to configure the process,
and finally calling PipelineBuilder.run() to start the process execution.
Once PipelineBuilder.run() is called, the builder may no longer be used.
Here's an example:
String result = ProcessBuilder.newBuilder("echo", "hello world")
.output().toSingleString(500)
.run();
In this example, a new process builder which calls the program echo is created.
A single argument (the string "hello world") is passed to the program.
The output of the program is configured to be captured as a single string of up to 500 characters,
and then the process is executed.
Since the output was configured using PipelineBuilder.Output.toSingleString(int), the process execution
returns a String.
If, for example, the output is discarded, then PipelineBuilder.run() would
return a Void (i.e., null).
Configuring builder parameters
Environment
When a new process builder is created, the environment of the current process is copied into the builder. This can be overridden by callingenvironment(Map) to replace the entire environment for the subprocess,
or modifyEnvironment(Consumer) to use a handler callback (typically a lambda) to perform arbitrary
manipulations of the environment map.
When creating a pipeline, the environment of the previous stage is used as the default environment for all subsequent stages.
Working directory
Process builders are initialized to use the working directory of the current process by default. This can be overridden by callingdirectory(Path).
The given path must exist on the default filesystem.
Subsequent pipeline stages inherit the working directory of previous stages by default.
Arguments
The command arguments may be given when constructing the builder, or thearguments(...) methods may be used to configure the arguments separately.
Timeouts
It is possible to configure a soft exit timeout and a hard exit timeout. These timeouts are used to cause the process to exit in the case where it lingers after all I/O is complete. The soft timeout will request a "normal" termination, if it is supported by that platform (i.e. not Windows), if that time elapses after I/O is complete but before the process exits. The hard timeout will forcefully terminate the subprocess if the process lingers for the given duration after the soft timeout has been triggered.Processing input and output
The methodsinput(), PipelineBuilder.output(), and PipelineBuilder.error() are used to configure the behavior
of the process input, output, and error output, respectively.
Each of these methods returns a view of this builder which has methods to configure that aspect of process I/O.
Input processing
Process input may be empty, inherited from the current process, transferred from a file, a reader, or a stream, generated from a string or a collection of strings, or produced via callback as characters orbytes.
When generating input as characters, the input character set is used.
By default, the builder will use the native character set,
but a specific character set can be configured by calling ProcessBuilder.Input.charset(Charset).
These methods have no effect when generating byte input.
Output processing
In addition to determining whether and how process output is consumed, configuring the output handling strategy also affects the type of the value returned by thePipelineBuilder.run() method.
In cases where the output type is impacted, the chaining method will return a view builder
whose type will reflect the new output type.
Therefore, the return value of each builder method should normally only be used
to call the next builder method,
and should not normally be saved or reused.
As with input, the native character set is used for output processing by default, but this can be configured as well.
Basic output targets
Process output can be discarded, inherited from the current process, transferred to a file (optionally in append mode), a writer, or a stream, consumed as bytes, characters, or lines.
The output can also be processed to produce a value of some type.
The single string and
list of strings processors are provided,
but a custom processor which handles process output as bytes
or characters may be provided.
The processor returns an object of the desired type, and on success, that value is returned
from PipelineBuilder.run().
It is also possible to configure the builder to capture the process output to include in
any thrown exception.
This is disabled by default but can be enabled by calling Output.gatherOnFail(true).
Multiple output handlers
It is also possible to split or "tee" a copy of the process output to one or more additional consumers. This can be useful, for example, to log the output of a process while also passing it on to another handler. TheOutput.copyAndXxx(...) methods work similarly to the primary output control methods,
but also copy the data to the given handler.
Error processing
Error output may be processed similarly to how output is processed, with the exception that error output cannot be piped to another pipeline stage.
It is also possible to merge the error output of the process into its regular output by calling
PipelineBuilder.Error.redirect().
The combined standard error and standard output will be merged and handled using the output handler.
Note that using this mode will prevent error output from being captured in the case of an exception.
Process pipelines
Process output can be configured to feed directly into the input of another process by calling one of theOutput.pipeTo(...) methods.
These methods return a new process builder to configure the subsequent pipeline stage.
Once the pipeTo(...) method is called, the builder for the original process can no longer be modified.
Thus, the output stage should generally be configured last.
Since the new process builder represents a subsequent pipeline stage whose input always comes from the previous stage, there is no way to configure input handling for subsequent pipeline stages. Additionally, timeouts apply to the entire pipeline, not to individual stages; thus, timeouts must be configured only on the first pipeline stage. Other parameters, such as the working directory, environment, etc. may be configured on a per-stage basis and normally inherit their settings from the previous stage.
Exit code validation
By default, if the process exits with a nonzero exit code it is assumed to have failed, which will trigger an exception to be thrown that details the problem. A custom exit code checker can be injected which can be used to capture and save the exit code and/or establish an alternative validation policy for exit codes. The checker is a predicate which returnstrue if the exit code is successful or false if
it should result in a failure exception being thrown.-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic interfaceThe input handling aspect of the process builder.Nested classes/interfaces inherited from interface io.smallrye.common.process.PipelineBuilder
PipelineBuilder.Error<O>, PipelineBuilder.Output<O> -
Field Summary
Fields -
Method Summary
Modifier and TypeMethodDescriptiondefault ProcessBuilder<O> Set the arguments for this process execution.Set the arguments for this process execution.Set the working directory for this process execution.default ProcessBuilder<O> environment(Map<String, String> newEnvironment) Set the environment for this process execution, overriding the inherited environment.static voidExecute the given command and arguments, discarding the result.static voidExecute the given command and arguments, discarding the result.static voidExecute the given command and arguments, discarding the result.static voidExecute the given command and arguments, discarding the result.static StringexecToString(String command, String... args) Execute the given command and arguments, returning the result as a single string.static StringexecToString(String command, List<String> args) Execute the given command and arguments, returning the result as a single string.static StringexecToString(Path command, String... args) Execute the given command and arguments, returning the result as a single string.static StringexecToString(Path command, List<String> args) Execute the given command and arguments, returning the result as a single string.exitCodeChecker(IntPredicate checker) Add a failure exit code checker.hardExitTimeout(Duration duration) Set the hard exit timeout.input()Configure the input handling of the process.modifyEnvironment(Consumer<Map<String, String>> action) Allow the given action to modify the environment of the subprocess.static ProcessBuilder<Void> newBuilder(String command) Create a new process builder.static ProcessBuilder<Void> newBuilder(String command, String... args) Create a new process builder.static ProcessBuilder<Void> newBuilder(String command, List<String> args) Create a new process builder.static ProcessBuilder<Void> newBuilder(Path command) Create a new process builder.static ProcessBuilder<Void> newBuilder(Path command, String... args) Create a new process builder.static ProcessBuilder<Void> newBuilder(Path command, List<String> args) Create a new process builder.softExitTimeout(Duration duration) Set the soft exit timeout.specialQuoting(boolean specialQuoting) Enable special quoting for batch scripts on Windows.whileRunning(Consumer<WaitableProcessHandle> action) Set the while-running process handler.Methods inherited from interface io.smallrye.common.process.PipelineBuilder
error, output, run, runAsync
-
Field Details
-
DEFAULT_SOFT_TIMEOUT
The default soft timeout duration. -
DEFAULT_HARD_TIMEOUT
The default hard timeout duration.
-
-
Method Details
-
exec
Execute the given command and arguments, discarding the result.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)
-
exec
Execute the given command and arguments, discarding the result.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)
-
exec
Execute the given command and arguments, discarding the result.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)
-
exec
Execute the given command and arguments, discarding the result.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)
-
execToString
Execute the given command and arguments, returning the result as a single string.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)- Returns:
- the result as a single string (not
null)
-
execToString
Execute the given command and arguments, returning the result as a single string.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)- Returns:
- the result as a single string (not
null)
-
execToString
Execute the given command and arguments, returning the result as a single string.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)- Returns:
- the result as a single string (not
null)
-
execToString
Execute the given command and arguments, returning the result as a single string.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)- Returns:
- the result as a single string (not
null)
-
newBuilder
Create a new process builder.- Parameters:
command- the command to execute (must not benull)- Returns:
- the new process builder (not
null)
-
newBuilder
Create a new process builder.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)- Returns:
- the new process builder (not
null)
-
newBuilder
Create a new process builder.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)- Returns:
- the new process builder (not
null)
-
newBuilder
Create a new process builder.- Parameters:
command- the command to execute (must not benull)- Returns:
- the new process builder (not
null)
-
newBuilder
Create a new process builder.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)- Returns:
- the new process builder (not
null)
-
newBuilder
Create a new process builder.- Parameters:
command- the command to execute (must not benull)args- the arguments (must not benull)- Returns:
- the new process builder (not
null)
-
arguments
Description copied from interface:PipelineBuilderSet the arguments for this process execution.- Specified by:
argumentsin interfacePipelineBuilder<O>- Parameters:
command- the arguments for this process execution (must not benull)- Returns:
- this builder
-
arguments
Description copied from interface:PipelineBuilderSet the arguments for this process execution.- Specified by:
argumentsin interfacePipelineBuilder<O>- Parameters:
command- the arguments for this process execution (must not benull)- Returns:
- this builder
-
specialQuoting
Description copied from interface:PipelineBuilderEnable special quoting for batch scripts on Windows. Note that this requires the batch script to use a specific form of argument expansion.- Specified by:
specialQuotingin interfacePipelineBuilder<O>- Parameters:
specialQuoting-trueto enable special quoting, orfalseto use default quoting- Returns:
- this builder
-
directory
Description copied from interface:PipelineBuilderSet the working directory for this process execution.- Specified by:
directoryin interfacePipelineBuilder<O>- Parameters:
directory- the working directory (must not benull)- Returns:
- this builder
-
environment
Description copied from interface:PipelineBuilderSet the environment for this process execution, overriding the inherited environment.- Specified by:
environmentin interfacePipelineBuilder<O>- Parameters:
newEnvironment- the new environment (must not benull)- Returns:
- this builder
-
modifyEnvironment
Description copied from interface:PipelineBuilderAllow the given action to modify the environment of the subprocess. The action is provided a mutable map which can be arbitrarily modified for the duration of the callback. Modifying the map after the callback returns will result in undefined behavior and should not be attempted.- Specified by:
modifyEnvironmentin interfacePipelineBuilder<O>- Parameters:
action- the action (must not benull)- Returns:
- this builder
-
exitCodeChecker
Description copied from interface:PipelineBuilderAdd a failure exit code checker. The checker returnstrueif the process execution should fail for this exit code. If so, aProcessExceptionwill be constructed and thrown. The exception will generally include some or all of the data received from the error stream of the subprocess.- Specified by:
exitCodeCheckerin interfacePipelineBuilder<O>- Parameters:
checker- the exit code checker (must not benull)- Returns:
- this builder
-
whileRunning
Description copied from interface:PipelineBuilderSet the while-running process handler.- Specified by:
whileRunningin interfacePipelineBuilder<O>- Parameters:
action- the action to run (must not benull)- Returns:
- this builder
-
input
ProcessBuilder.Input<O> input()Configure the input handling of the process.- Returns:
- the input configuration view of this builder (not
null)
-
softExitTimeout
Set the soft exit timeout. This is the time to wait after all I/O is processed before gracefully terminating the subprocess.- Parameters:
duration- the soft exit timeout, ornullfor no timeout- Returns:
- this builder
-
hardExitTimeout
Set the hard exit timeout. This is the time to wait after all I/O is processed and the soft timeout has elapsed before forcefully terminating the subprocess.- Parameters:
duration- the hard exit timeout, ornullfor no timeout- Returns:
- this builder
-