bashprocess-substitution

How to detect errors with process substitution?


There appears to be no way to capture that the process from within exited with non-zero status:

cat < <( echo inside; exit 1; echo nomore; ) || echo error
echo "${PIPESTATUS[*]}"

Gives:

inside
0

Is what happened inside essentially irretrievable, unlike with pipes?


Solution

  • How to detect errors with process substitution?

    1. Do not use process substitution. Use something else, that allows to capture exit code. Like coproc or bacground process.

    Note that coproc has some isses, which is why I don't like it much. In particular, the COPROC variable dissapears after the pid exits. You just have to copy it....

    coproc { echo inside; exit 1; echo nomore; }
    fd=${COPROC[0]}
    pid=$COPROC_PID
    cat <&"$fd"
    ret=0
    wait "$pid" || ret=$?
    if ((ret != 0)); then
       echo "coproc failed with exit code $ret!"
    fi
    
    1. Or use a method of interprocess communication to transfer the exit code of the commands inside process substition to your program.

    There are several ways of interprocess communication. The simplest and predominantly used in shell is a file.

    if ! cat < <( 
       ( echo inside; exit 1; echo nomore; ) || echo $? > /tmp/file
    ); then
      echo "cat failed!"
    fi
    ret=$(</tmp/file)
    if ((ret != 0)); then
      echo "process substitution failed with exit code $ret!"
    fi
    

    For example, there are also signals on Wikipedia, we can use them too.

    err=0
    trap 'err=1' SIGUSR1
    parentpid=$BASHPID
    if 
      ! cat < <( 
         ( echo inside; exit 1; echo nomore; ) || kill -sSIGUSR1 $parentpid
      ) ||
      ((err != 0))
    then
      echo "cat or process substitution failed"
    fi