简体   繁体   English

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

[英]Is there a way to use `script` with shell functions? (colorized output)

I'm using a script to run several tests (npm, python etc...) 我正在使用脚本运行多个测试(npm,python等...)

These have colored outputs. 这些都有彩色输出。

I'm actually running some of these tests in parallel sending processes in the background, and capturing output in a variable to display when done (as opposed to letting the output come to TTY and having multiple outputs mixed up together). 我实际上在后台并行发送进程中运行其中一些测试,并在变量中捕获输出以在完成时显示(而不是让输出到达TTY并将多个输出混合在一起)。

All works well, but the output is not colored, and I would like to keep the colors. 一切都很好,但输出没有颜色,我想保持颜色。 I understand it is because it is not an output to a TTY so color is stripped, and I looked for tricks to avoid this. 我明白这是因为它不是TTY的输出,所以颜色被剥离,我寻找诀窍来避免这种情况。

This answer: Can colorized output be captured via shell redirect? 这个答案: 可以通过shell重定向捕获彩色输出吗?

offers a way to do this, but doesn't work with shell functions 提供了一种方法,但不适用于shell函数

If I do: 如果我做:

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

I get the output in the variable and the echo command output is colored. 我得到变量中的输出,并且echo命令输出是彩色的。

but if f I do: 但如果我这样做:

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

I get: 我明白了:

script: run_test: No such file or directory

If I call the run_test function passing it to script like: 如果我调用run_test函数将其传递给脚本,如:

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

it's like passing the output that is already eval'd without the colors, so the script output is not colored. 这就像传递已经没有颜色的eval'd的输出,因此脚本输出没有着色。

Is there a way to make shell functions work with script ? 有没有办法使shell函数与script

I could have the script call in the function like: 我可以在函数中调用脚本:

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

but there are several issues with that: 但是有几个问题:

  • Sometimes I need to run multiple commands in series, and send that in the background to run in parallel, it becomes messy: I want to wrap sequences in a shell function and run that with script. 有时我需要串行运行多个命令,并在后台发送它并行运行,它变得很乱:我想在shell函数中包装序列并用脚本运行它。
  • This would already run the function itself, and return when done. 这已经运行了函数本身,并在完成后返回。 What I want is pass the function to call to another function that runs in the background and logs the output with script. 我想要的是传递函数来调用另一个在后台运行的函数并使用脚本记录输出。

PS: I also tried npm config set color always to force npm to always output colors, but that doesn't seem to help, plus I have other functions to call that are not all npm, so it would not work for everything anyways. PS:我也试过npm config set color always迫使npm总是输出颜色,但这似乎没有帮助,加上我有其他函数来调用并非所有npm,所以它不适用于所有事情。

You can use a program such as unbuffer that simulates a TTY to get color output from software whose output is actually eventually going to a pipeline. 您可以使用模拟TTY的unbuffer等程序从输出实际最终进入管道的软件中获取颜色输出。

In the case of: 如果是:

unbuffer npm test | cat

...there's a TTY simulated by unbuffer , so it doesn't see the FIFO going to cat on its output. ...有一个由unbuffer模拟的TTY,因此它没有看到FIFO在其输出上变为cat

If you want to run a shell function behind a shim of this type, be sure to export it to the environment, as with export -f . 如果要在此类型的垫片后面运行shell函数,请确保将其导出到环境中,就像export -f


Demonstrating how to use this with a shell function: 演示如何在shell函数中使用它:

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

I tried unbuffer and it doesn't seem to work with shell functions either 我尝试了unbuffer ,它似乎也不适用于shell函数

script doesn't work by passing it a shell function, however it's possible to pass some STDIN type input, so what ended up working for me was 脚本通过传递shell函数不起作用,但是可以传递一些STDIN类型的输入,所以最终为我工作的是

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

or 要么

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

so I could output this to a shell variable, even using a variable as the COMMAND like: 所以我可以将它输出到shell变量,甚至使用变量作为COMMAND,如:

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

and later output the colored output with 然后输出彩色输出

echo -e $OUTPUT

Unfortunately, this still outputs some extra garbage (ie the shell name, the command name and the exit command at the end. 不幸的是,这仍然会输出一些额外的垃圾(即shell名称,命令名称和最后的exit命令)。

Since I wanted to capture the output code, I could not pipe the output somewhere else, so I went this way: 由于我想捕获输出代码,我无法在其他地方输出输出,所以我这样做:

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
    }

and use like: 并使用如下:

# 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

I'm skipping the part where I catch the errors and propagate failure to the top PID, but you get the gist. 我正在跳过我捕获错误并将失败传播到顶级PID的部分,但是你得到了要点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM