Skip to content

Add stderr operators: 2>, 2>>, |&, 2>&1 #535

Description

@stalep

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions