Unexpected behaviour when using process substitution with stdout and stderr

2021-07-11 Thread earnestly
GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-gnu)

I have attempted to use process substitution in order to feed the
output of a command into two filters, one for handling stdout and the
other for stderr.

Prior to this I was using POSIX sh and named pipes to achieve this but
decided to try bash with its >() and <() notation.

Perhaps I am misunderstanding how this works because I found them to be
unusable in this context.

What appears to be happening is that the output from standard error is
being mixed into the function handling standard out, even more
surprisingly that xtrace output is also being consumed and filtered as
well.

I don't quite know how to describe what's happening so I have provided a
small demonstration/reproducer instead:

#!/bin/bash --

generate() {
for ((i=0; i<10; ++i)); do
if ((RANDOM % 2)); then
printf 'generate to stdout\n'
else
printf 'generate to stderr\n' >&2
fi
done
}

stdout() {
local line

while read -r line; do
printf 'from stdout: %s\n' "$line"
done
}

stderr() {
local line

while read -r line; do
printf 'from stderr: %s\n' "$line"
done
}

# Using process substitution.
unexpected() {
# This is particularly dangerous when the script is executed under `bash -x'
# as the xtrace output is read as standard input to the `stdout' function.
generate > >(stdout) 2> >(stderr)
wait

# Example output:
# from stdout: generate to stdout
# from stdout: generate to stdout
# from stdout: from stderr: generate to stderr
# from stdout: from stderr: generate to stderr
# from stdout: from stderr: generate to stderr
# from stdout: generate to stdout
# from stdout: from stderr: generate to stderr
# from stdout: generate to stdout
# from stdout: from stderr: generate to stderr
# from stdout: from stderr: generate to stderr
}

# Using named pipes.
expected() {
mkfifo a b
trap 'rm a b' EXIT

generate > a 2> b &

stdout < a &
stderr < b &
wait

# Example output:
# from stdout: generate to stdout
# from stderr: generate to stderr
# from stdout: generate to stdout
# from stderr: generate to stderr
# from stdout: generate to stdout
# from stdout: generate to stdout
# from stderr: generate to stderr
# from stdout: generate to stdout
# from stdout: generate to stdout
# from stderr: generate to stderr
}



Re: Unexpected behaviour when using process substitution with stdout and stderr

2021-07-11 Thread Alex fxmbsw7 Ratchev
you printf basically to stdout from stderr, ..maybe its that
if you'd change your stderr printf to >&2 maybe works, ..just saying, maybe
or change the order to 2> and then >
..maybe..

peace

On Sun, Jul 11, 2021, 12:09 earnestly  wrote:

> GNU bash, version 5.1.8(1)-release (x86_64-pc-linux-gnu)
>
> I have attempted to use process substitution in order to feed the
> output of a command into two filters, one for handling stdout and the
> other for stderr.
>
> Prior to this I was using POSIX sh and named pipes to achieve this but
> decided to try bash with its >() and <() notation.
>
> Perhaps I am misunderstanding how this works because I found them to be
> unusable in this context.
>
> What appears to be happening is that the output from standard error is
> being mixed into the function handling standard out, even more
> surprisingly that xtrace output is also being consumed and filtered as
> well.
>
> I don't quite know how to describe what's happening so I have provided a
> small demonstration/reproducer instead:
>
> #!/bin/bash --
>
> generate() {
> for ((i=0; i<10; ++i)); do
> if ((RANDOM % 2)); then
> printf 'generate to stdout\n'
> else
> printf 'generate to stderr\n' >&2
> fi
> done
> }
>
> stdout() {
> local line
>
> while read -r line; do
> printf 'from stdout: %s\n' "$line"
> done
> }
>
> stderr() {
> local line
>
> while read -r line; do
> printf 'from stderr: %s\n' "$line"
> done
> }
>
> # Using process substitution.
> unexpected() {
> # This is particularly dangerous when the script is executed under
> `bash -x'
> # as the xtrace output is read as standard input to the `stdout'
> function.
> generate > >(stdout) 2> >(stderr)
> wait
>
> # Example output:
> # from stdout: generate to stdout
> # from stdout: generate to stdout
> # from stdout: from stderr: generate to stderr
> # from stdout: from stderr: generate to stderr
> # from stdout: from stderr: generate to stderr
> # from stdout: generate to stdout
> # from stdout: from stderr: generate to stderr
> # from stdout: generate to stdout
> # from stdout: from stderr: generate to stderr
> # from stdout: from stderr: generate to stderr
> }
>
> # Using named pipes.
> expected() {
> mkfifo a b
> trap 'rm a b' EXIT
>
> generate > a 2> b &
>
> stdout < a &
> stderr < b &
> wait
>
> # Example output:
> # from stdout: generate to stdout
> # from stderr: generate to stderr
> # from stdout: generate to stdout
> # from stderr: generate to stderr
> # from stdout: generate to stdout
> # from stdout: generate to stdout
> # from stderr: generate to stderr
> # from stdout: generate to stdout
> # from stdout: generate to stdout
> # from stderr: generate to stderr
> }
>
>


Re: Unexpected behaviour when using process substitution with stdout and stderr

2021-07-11 Thread Greg Wooledge
On Sun, Jul 11, 2021 at 11:09:10AM +0100, earnestly wrote:
> What appears to be happening is that the output from standard error is
> being mixed into the function handling standard out, even more
> surprisingly that xtrace output is also being consumed and filtered as
> well.

First, xtrace (set -x) output is written to stderr by default.  You can
change this by setting the BASH_XTRACEFD variable.  But in the absence
of that change, it goes to stderr, along with any other content that's
written to stderr, either by bash itself, or by commands that bash calls.

> stdout() {
> local line
> 
> while read -r line; do
> printf 'from stdout: %s\n' "$line"
> done
> }
> 
> stderr() {
> local line
> 
> while read -r line; do
> printf 'from stderr: %s\n' "$line"
> done
> }

> generate > >(stdout) 2> >(stderr)
> wait

You're sending the stderr of generate to a subshell where the stderr()
function is executed.  But the stderr() function writes to stdout.
Therefore, all of the output from generate is ultimately ending up going
to the script's stdout, with potentially weird interleaving depending
on the timing of the two background subshells.

If you want to keep them separate, you either need to change the stderr()
function to write to stderr, or change the >(stderr) call to >(stderr >&2).



Re: Unexpected behaviour when using process substitution with stdout and stderr

2021-07-11 Thread Andreas Schwab
On Jul 11 2021, Greg Wooledge wrote:

> You're sending the stderr of generate to a subshell where the stderr()
> function is executed.  But the stderr() function writes to stdout.
> Therefore, all of the output from generate is ultimately ending up going
> to the script's stdout, with potentially weird interleaving depending
> on the timing of the two background subshells.

There is no interleaving.  The output of stderr is connected to the
current disposition of fd 1 which is redirected to the >(stdout) pipe.
You can either switch the order of redirections, or save the previous
disposition of fd 1 in another fd and redirect the output of stderr
there.

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



Re: Bash-5.1-rc3 available

2021-07-11 Thread Chet Ramey

On 7/10/21 6:03 PM, Alex fxmbsw7 Ratchev wrote:

is this --branch bash-5.1-testing stilk actual, or should i use devel


No. It's for pre-release versions of bash-5.1. If you want to keep up with
development, use the devel branch.


--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: Bash-5.1-rc3 available

2021-07-11 Thread Alex fxmbsw7 Ratchev
thank you

On Sun, Jul 11, 2021, 20:51 Chet Ramey  wrote:

> On 7/10/21 6:03 PM, Alex fxmbsw7 Ratchev wrote:
> > is this --branch bash-5.1-testing stilk actual, or should i use devel
>
> No. It's for pre-release versions of bash-5.1. If you want to keep up with
> development, use the devel branch.
>
>
> --
> ``The lyf so short, the craft so long to lerne.'' - Chaucer
>  ``Ars longa, vita brevis'' - Hippocrates
> Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
>