将stderr和stdout作为变量发送到函数并检查类型

时间:2018-01-22 12:44:19

标签: bash

我正在使用2>&1 | MyFunction

将脚本的输出重定向到我编写的函数

这很有效。但是,我很难确定如何确定STDOUT中传递的变量是STDERR还是MyFunction

例如:

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

如果它是STDOUTSTDERR的实例,是否有某种方法可以对传递的变量执行检查,以便我可以根据它执行条件规则?

3 个答案:

答案 0 :(得分:2)

管道将传送标准输出(STDOUT)数据。 2>&1将标准错误(“2”)重定向到文件描述符“1”,这是标准输出。

这意味着以下行: myCommand 2>&1 | MyFunction 可以读作“运行myCommand,将标准错误重定向到标准输出,并在输出上运行MyFunction(这是标准错误+标准输出)”

一旦你写了2>&1,就无法知道哪条线最初发送到STDOUT或STDERR。

答案 1 :(得分:1)

不直接,不。如果你不需要与Bash之外的其他shell兼容,你可以在Bash中使用一些技巧来为每一行添加前缀;例如

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.

如您所见,两个sed进程的输出重新组合为标准输出,然后通过管道传输作为行编号程序nl的标准输入。大括号将命令分组,以便最终重定向2>&1不会直接影响Perl进程。

答案 2 :(得分:1)

您可以使用:

# 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