有没有办法将`script`用于shell函数? (彩色输出)

时间:2017-07-29 20:37:05

标签: bash shell

我使用脚本运行多个测试(npm,python等...)

这些有彩色输出。

我实际上在后台并行发送进程中运行其中一些测试,并在变量中捕获输出以在完成时显示(而不是让输出到达TTY并将多个输出混合在一起)

一切运作良好,但输出没有着色,我想保留颜色。我理解这是因为它不是TTY的输出所以颜色被剥离了,我寻找诀窍来避免这种情况。

这个答案: Can colorized output be captured via shell redirect?

提供了一种方法,但不能使用shell函数

如果我这样做:

OUTPUT=$(script -q /dev/null npm test | cat)
echo -e $OUTPUT

我得到变量中的输出,echo命令输出是彩色的。

但如果我这样做:

function run_test() { npm test; }
OUTPUT=$(script -q /dev/null run_test | cat)
echo -e $OUTPUT

我明白了:

script: run_test: No such file or directory

如果我调用run_test函数将其传递给脚本,如:

function run_test() { npm test; }
OUTPUT=$(script -q /dev/null `run_test` | cat)
echo -e $OUTPUT

就像传递已经没有颜色的eval&d的输出一样,所以脚本输出没有着色。

有没有办法让shell函数与script一起使用?

我可以在函数中调用脚本:

function run_test() { script -q /dev/null npm run test | cat; }

但是有几个问题:

  • 有时候我需要连续运行多个命令,然后在后台发送它并行运行,它变得很乱:我想把序列包装在shell函数中并用脚本运行它。
  • 这已经运行了函数本身,并在完成后返回。我想要的是传递函数来调用另一个在后台运行的函数,并用脚本记录输出。

PS:我也尝试npm config set color always强制npm总是输出颜色,但这似乎没有帮助,而且我还有其他函数可以调用并非所有npm,所以它不起作用反正一切。

2 个答案:

答案 0 :(得分:2)

您可以使用模拟TTY的unbuffer等程序从输出实际最终进入管道的软件中获取颜色输出。

以下情况:

unbuffer npm test | cat

...有一个由unbuffer模拟的TTY,所以它没有看到FIFO输出到cat

如果要在此类型的垫片后面运行shell函数,请务必将其导出到环境中,与export -f一样。

演示如何在shell函数中使用它:

myfunc() { echo "In function"; (( $# )) && { echo "Arguments:"; printf ' - %s\n' "$@"; }; }
export -f myfunc
unbuffer bash -c '"$@"' _ myfunc "Argument one" "Argument two"

答案 1 :(得分:0)

我尝试了unbuffer,它似乎无法使用shell函数

脚本没有通过传递shell函数来工作,但是它可以传递一些STDIN类型的输入,所以最终为我工作的是

script -q /dev/null <<< "run_test"

echo "run_test" | script -q /dev/null

所以我可以将它输出到shell变量,即使使用变量作为COMMAND,如:

OUTPUT=$(echo "$COMMAND" | script -q /dev/null)

然后用

输出彩色输出
echo -e $OUTPUT

不幸的是,这仍然会输出一些额外的垃圾(即shell名称,命令名称和exit命令。

由于我想捕获输出代码,我无法在其他地方输出输出,所以我这样做了:

run() {
    run_in_background "$@" &
}    

run_in_background() {    
        COMMAND="$@" # whatever is passed to the function    
        CODE=0

        OUTPUT=$(echo "$COMMAND" | script -q /dev/null) || CODE=$(( CODE + $? ));

        echo -e $OUTPUT | grep -v "bash" | grep -v "$COMMAND";
        if [ "$CODE" != "0" ]; then exit 1; fi
    }

并使用如:

# test suites shell functions
run_test1() { npm test; }
run_test2() { python manage.py test; }

# queue tests to run in background jobs
run run_test1
run run_test2
# wait for all to finish
wait

我跳过了我捕获错误的部分,并将失败传播到顶级PID,但是你得到了要点。