Summary
Implement stderr redirection and piping operators. The OperatorType enum already defines these types but they are not wired in Executions.buildOperator() and the infrastructure for a separate stderr channel does not exist.
Operators to implement
| Operator |
Description |
Example |
2> |
Redirect stderr to file (overwrite) |
cmd 2> errors.log |
2>> |
Redirect stderr to file (append) |
cmd 2>> errors.log |
|& |
Pipe both stdout and stderr |
cmd |& grep error |
2>&1 |
Merge stderr into stdout |
cmd > out.txt 2>&1 |
Current state
OperatorType defines PIPE_AND_ERROR, REDIRECT_OUT_ERROR, APPEND_OUT_ERROR, REDIRECT_OUT_ALL
Executions.buildOperator() throws IllegalArgumentException for all of them
- Commands have no separate stderr channel — all output goes through
Shell.write() / CommandInvocation.println()
Design considerations
1. Stderr channel for commands
Commands need a way to write to stderr separately from stdout:
// Option A: explicit method
commandInvocation.printErr("Error: file not found");
// Option B: stderr stream
commandInvocation.getStderr().write(...);
This requires:
- A stderr
OutputDelegate on CommandInvocationConfiguration
ShellOutputDelegate handling two output streams (stdout delegate + stderr delegate)
- Default behavior when no stderr redirection: write to the terminal (same as stdout)
2. Backward compatibility
Most existing commands use println() for everything including error messages. Options:
println() remains stdout-only (breaking for commands that print errors via println)
- Add
printErr() as the new explicit stderr path, println() unchanged
- Provide a
System.err-like accessor for commands that want separation
3. Operator wiring
Each operator needs a case in Executions.buildOperator() and appropriate CommandInvocationConfiguration construction in buildExecution().
For 2>&1, stderr is merged into the stdout OutputDelegate. For |&, both stdout and stderr flow into the PipeOperator queue. For 2> / 2>>, only stderr goes to the file while stdout continues to the terminal.
4. Interaction with streaming pipes (#532)
The streaming pipe implementation uses PipeOutputDelegate for stdout. |& would need to route both stdout and stderr through the same queue. The QueueOutputStream is already thread-safe (uses BlockingQueue.put()), so both channels can write to it concurrently.
Dependencies
Related
Summary
Implement stderr redirection and piping operators. The
OperatorTypeenum already defines these types but they are not wired inExecutions.buildOperator()and the infrastructure for a separate stderr channel does not exist.Operators to implement
2>cmd 2> errors.log2>>cmd 2>> errors.log|&cmd |& grep error2>&1cmd > out.txt 2>&1Current state
OperatorTypedefinesPIPE_AND_ERROR,REDIRECT_OUT_ERROR,APPEND_OUT_ERROR,REDIRECT_OUT_ALLExecutions.buildOperator()throwsIllegalArgumentExceptionfor all of themShell.write()/CommandInvocation.println()Design considerations
1. Stderr channel for commands
Commands need a way to write to stderr separately from stdout:
This requires:
OutputDelegateonCommandInvocationConfigurationShellOutputDelegatehandling two output streams (stdout delegate + stderr delegate)2. Backward compatibility
Most existing commands use
println()for everything including error messages. Options:println()remains stdout-only (breaking for commands that print errors via println)printErr()as the new explicit stderr path,println()unchangedSystem.err-like accessor for commands that want separation3. Operator wiring
Each operator needs a case in
Executions.buildOperator()and appropriateCommandInvocationConfigurationconstruction inbuildExecution().For
2>&1, stderr is merged into the stdout OutputDelegate. For|&, both stdout and stderr flow into the PipeOperator queue. For2>/2>>, only stderr goes to the file while stdout continues to the terminal.4. Interaction with streaming pipes (#532)
The streaming pipe implementation uses
PipeOutputDelegatefor stdout.|&would need to route both stdout and stderr through the same queue. TheQueueOutputStreamis already thread-safe (usesBlockingQueue.put()), so both channels can write to it concurrently.Dependencies
Related
OperatorType.java— enum definitions already exist