从内部删除 bash 脚本的颜色和重定向输出

Remove color and redirect ouptut of a bash script from within

我的问题很简单,如何将 bash 脚本的所有输出重定向到 文件和终端 以及 删除颜色 个字符 来自 脚本本身?

我找不到满足我所有需求的答案。

到目前为止,我尝试了 tee 输出到文件和终端,结合 2>&1 得到 stederrstdoutsed 去除颜色字符和所有这些 exec 从我的脚本中完成,但它不起作用,我只在终端中获取彩色日志,文件中没有任何内容。

#!/usr/bin/env bash
exec 2>&1 | sed -r 's/\x1b\[[0-9;]*m//g' | tee script.logs

python somepython.py
python someotherpython.py

此处 python 脚本生成彩色输出。

我想将这些记录到终端(未触及)和文件(没有颜色)中。实际上,我的 bash 脚本中发生的事情比这两个 python 脚本要多得多,这就是为什么我想全局重定向我的脚本 bash 的输出,而不仅仅是在之后进行管道传输每个 python 个脚本。

因此我使用了 exec 因为我虽然它允许重定向脚本产生的所有输出。

在此先感谢您的任何建议和帮助,

PS:我不想在文件中使用彩色日志,但我不在乎终端是否需要这样做才能使日志在文件中不被着色。

您可以将所有呼叫放在花括号组中并重定向所有呼叫,例如:

#!/usr/bin/env bash
{
  python somepython.py
  python someotherpython.py
} 2>&1 | sed -r 's/\x1b\[[0-9;]*m//g' | tee script.logs

这样,所有 stdout 和 stderr 输出都将通过过滤器。

为终端而不是文件着色

如果您想将颜色写入终端并将未着色的文本写入文件,您可以将 sed 过滤器应用于 tee 写入的文件,例如你的脚本看起来像:

#!/usr/bin/env bash
{
  python somepython.py
  python someotherpython.py
} 2>&1 | tee >(sed -r 's/\x1b\[[0-9;]*m//g' > script.logs)

这使用了 process substitution,这是 bash 中非常强大的工具,尽管一开始有点困难。

删除缓冲

假设您想尽快阅读内容,您可能需要停用 python 的块缓冲。这可以使用 -u 选项来完成:

#!/usr/bin/env bash
{
  python -u somepython.py
  python -u someotherpython.py
} 2>&1 | tee >(sed -r 's/\x1b\[[0-9;]*m//g' > script.logs)

旁注:谨防 CSI

并非所有特殊字符都基于控制序列启动器 ESC [

如果使用 tput setaf 1 将文本着色为绿色,它将使用控制序列 ESC [31m,但如果使用 tput sgr0 重置颜色,则控制序列可能是 ESC (B ESC [m(请注意 ESC (B 序列)。因此,如果您仅过滤 ESC [ 序列,您的日志文件中可能仍有控制序列浪费。

如果程序使用其他类型的控制字符(例如光标命令),情况会变得更糟。

出于这些原因,避免问题的最佳方法就是避免从 python 脚本中编写控制序列。大多数内置程序通过在选择是否显示颜色之前检查输出是否为终端来防止这种情况。当输出不是终端时,它假定颜色可能会导致问题。

话虽如此,我不知道您是否可以控制 python 脚本(或您可能拥有的其他调用),但如果可以,您可能想测试输出是否为终端。在 Bash 中,您可以这样检查:

if [ -t 1 ] # does stdout end up on a terminal?
then
  # Display fancy colors
else
  # Minimalist display
fi

在 Python 中将是:

if sys.stdout.isatty(): # does stdout end up on a terminal?
  # Display fancy colors
else:
  # Minimalist display