我使用脚本运行多个测试(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; }
但是有几个问题:
PS:我也尝试npm config set color always
强制npm总是输出颜色,但这似乎没有帮助,而且我还有其他函数可以调用并非所有npm,所以它不起作用反正一切。
答案 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,但是你得到了要点。