xonsh icon indicating copy to clipboard operation
xonsh copied to clipboard

Implement pipefail and errexit

Open hexagonrecursion opened this issue 3 years ago • 3 comments

I want to know when a command other then the last command in the pipeline fails for any reason. If a command in the middle of a pipeline fails, the last command simply sees a EOF in its stdin. In many cases this will result in the last command returning success. Silently ignoring such errors can lead to all kinds of data loss, data corruption, truncation and other badness. Ideally any unhandled errors should terminate the script.

bash has pipefail:

#!/usr/bin/env bash
set -o errexit -o pipefail
echo one
false | true
echo two

VVV

one

Note: the above example does not print "two"

#!/usr/bin/env xon.sh
$RAISE_SUBPROC_ERROR = True
echo one
false | true
echo two

VVV

one
two

For community

⬇️ Please click the 👍 reaction instead of leaving a +1 or 👍 comment

hexagonrecursion avatar Jul 01 '21 15:07 hexagonrecursion

More context: Executing an external command can fail for a million different reasons. Here are some examples:

  1. The external command is not installed
  2. It encounters an internal bug and fails fast and loud
  3. It receives bad input due to a bug in my script
  4. An admin kills it
  5. The OOM Killer kills it https://linuxwheel.com/oom-killer-explained/
  6. It tries to talk to another process possibly on a different machine and that fails for any reason
  7. It uses a temporary file for internal buffering and /tmp is full
  8. It tries to read or write a file and that fails for any reason

A robust script can not afford to ignore the possibility that any of the external commands it executes may fail. Often the right choice of action is to fail fast because the code that follows requires that the preceding commands executed successfully.

Unix-y pipelines have an issue:

foo | bar

If foo exits successfully bar sees EOF. If foo fails bar also sees EOF. bar has no way to know whether foo failed or not. In many cases bar will exit successfully even if foo fails. The script has to detect that and fail. This is why you often see set -o errexit -o pipefail in bash.

Unfortunately set -o errexit is very broken in bash which is why I'm looking for a different shell.

hexagonrecursion avatar Jul 04 '21 10:07 hexagonrecursion

I also miss this feature, which is quite important in my opinion. Two use cases are

pv input | foo (pv = pipe viewer, it generates progress output at stderr)

and

foo | tee logfile

I guess these use cases are rather common, but the lack of some pipefail equivalent makes them painful with xonsh.

carhe avatar Sep 06 '22 11:09 carhe