1

I am redirecting the output of a script to a function I've written by using 2>&1 | MyFunction

This works great. However, I'm having a difficult time figuring out how to determine if the variable being passed is STDOUT or STDERR in MyFunction

Ex:

function MyFunction {
    while read line; do
        read IN
        echo "LOG: $IN" >> $LOG_FILE;
    done    
}

Is there some way the perform a check on the passed variable if it is an instance of either STDOUT or STDERR so I can perform conditional rules based upon it?

GrumpyCrouton
  • 8,486
  • 7
  • 32
  • 71
Ole Haugset
  • 3,709
  • 3
  • 23
  • 44

3 Answers3

2

The pipe will convey standard output (STDOUT) data. The 2>&1 redirects the standard error ("2") to the file descriptor "1", which is the standard output.

This means the following line : myCommand 2>&1 | MyFunction can be read as "Run myCommand, redirect the standard error to the standard output, and run MyFunction on the output (which is standard error + standard output)"

Once you've written 2>&1, there is no way to know which line was initially sent to STDOUT or STDERR.

fzd
  • 765
  • 1
  • 6
  • 19
1

Not directly, no. If you don't need to be compatible to other shells than Bash, you can use a bit of trickery in Bash to add a prefix to every line; for example

bash$ { perl -le 'print "oops"; die' 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /'); } 2>&1 | nl
 1  stdout: oops
 2  stderr: Died at -e line 1.

As you can see, the output from the two sed processes is recombined into standard output, which is then piped as standard input to the line numbering program nl. The braces group the commands so that the final redirection 2>&1 doesn't directly affect the Perl process.

tripleee
  • 175,061
  • 34
  • 275
  • 318
1

You can use this:

# call the function like:
# cmd | log err
# cmd | log info    
log() {
    type="${1}"
    while read -r line ; do
        if [ "${type}" = "err" ] ; then
            echo "EE ${line}"
        else
            echo "II ${line}"
        fi
    done
}

# Check this: https://stackoverflow.com/a/9113604/171318
# Use another file descriptor to separate between stdout and stderr
{ stdbuf -eL -oL cmd 2>&3 | log info ; } 3>&1 1>&2 | log err
# PS: ^ stdbuf makes sure that lines in output are in order
hek2mgl
  • 152,036
  • 28
  • 249
  • 266