bash:以红色打印 stderr

kol*_*pto 144 bash color stderr

有没有办法让 bash以红色显示stderr消息?

Bal*_*sár 115

command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
Run Code Online (Sandbox Code Playgroud)

  • 很棒的提示!建议:通过在`; 之前添加`>&2` done)`,用于 stderr 的输出实际上已写入 stderr。如果您想捕获程序的正常输出,这会很有帮助。 (9认同)
  • 伟大的!但我想知道是否有办法让它永久:) (8认同)
  • 以下使用`tput`,在我看来更易读:`command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done) ` (8认同)
  • 我认为为每个输出行执行 2 个 tput 进程一点也不优雅。也许如果您将 tput 命令的输出存储在一个变量中并将它们用于每个回声。但话又说回来,可读性并不是真的更好。 (3认同)
  • 此解决方案不保留空格,但我喜欢它的简洁性。`IFS= read -r line` 应该有帮助,但没有。不知道为什么。 (2认同)

小智 108

方法一:直接使用进程替换:

command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)
Run Code Online (Sandbox Code Playgroud)

方法二:在 bash 或 zsh 中创建函数:

color()(set -o pipefail;"$@" 2> >(sed $'s,.*,\e[31m&\e[m,'>&2))
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

$ color command
Run Code Online (Sandbox Code Playgroud)

这两种方法都会stderr以红色显示命令。

继续阅读以了解其工作原理。这些命令展示了一些有趣的功能。前 3 个要点仅适用于方法 2。其余的适用于这两种方法。

  • color()... — 创建一个名为 color 的 bash 函数。
  • set -o pipefail— 这是一个 shell 选项,用于保留命令的错误返回代码,该命令的输出通过管道传输到另一个命令。这是在由括号创建的子外壳中完成的,以免更改外壳中的 pipefail 选项。
  • "$@"— 将函数的参数作为新命令执行。 "$@"相当于"$1" "$2" ...
  • 2> >(...)>(...)语法称为进程替换。在 之前2> ,它将stderr主命令的连接到括号内stdinsed进程的 。
  • sed ...— 由于上面的重定向,sed'sstdinstderr已执行命令的。它的功能是用颜色代码包围每一行。
  • $'...' 一个 bash 构造,使其能够理解反斜杠转义的字符
  • .* — 匹配整行。
  • \e[31m — ANSI 转义序列导致以下字符变为红色
  • &sed扩展为整个匹配字符串(在本例中为整行)的替换字符。
  • \e[m — 重置颜色的 ANSI 转义序列。
  • >&2— 的简写1>&2,这会将sed's重定向stdoutstderr

  • +1 最佳答案!绝对被低估了! (9认同)
  • 很好的答案,甚至更好的解释 (3认同)
  • ZSH 无法识别速记重定向形式。它只需要另外两个 1,即:```zsh: color()(set -o pipefail;"$@" 2>&1 1>&3|sed $'s,.*,\e[31m&\e[m ,'1>&2)3>&1``` (2认同)
  • 这不会保留执行顺序。 (2认同)

sic*_*ill 30

您还可以查看 stderred:https : //github.com/sickill/stderred

  • 这实在是太巧妙了。这是我见过的唯一不会打乱 stdout 和 stderr 顺序的答案(据我所知,所有基于 shell 的解决方案都会打乱)。 (3认同)
  • 在 OS X El Capitan 中,这种工作方式 (DYLD_INSERT_LIBRARIES) 在系统二进制文件中被“破坏”,因为它们受 SIP 保护。因此,最好使用其他答案中给出的 bash 选项。 (2认同)

小智 18

使stderr永久变红的 bash 方法是使用“exec”来重定向流。将以下内容添加到您的 bashrc:

exec 9>&2
exec 8> >(
    while IFS='' read -r line || [ -n "$line" ]; do
       echo -e "\033[31m${line}\033[0m"
    done
)
function undirect(){ exec 2>&9; }
function redirect(){ exec 2>&8; }
trap "redirect;" DEBUG
PROMPT_COMMAND='undirect;'
Run Code Online (Sandbox Code Playgroud)

我之前已经发布过:如何为 STDOUT 和 STDERR 设置字体颜色


kol*_*pto 7

我制作了一个包装脚本,它在纯 bash 中实现了 Balázs Pozsár 的答案。将其保存在您的 $PATH 和前缀命令中以对其输出进行着色。

    #!/bin/bash

    if [ $1 == "--help" ] ; 然后
        echo "执行命令并为发生的所有错误着色"
        echo "示例:`basename ${0}` wget ..."
        echo "(c) o_O Tync,ICQ# 1227-700,享受吧!"
        退出 0
        菲

    # 捕获所有错误的临时文件
    TMP_ERRS=$(mktemp)

    # 执行命令
    "$@" 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" | tee --append $TMP_ERRS; done)
    退出代码=$?

    # 再次显示所有错误
    如果 [ -s "$TMP_ERRS" ] ; 然后
        echo -e "\n\n\n\e[01;31m === 错误 === \e[0m"
        猫 $TMP_ERRS
        菲
    rm -f $TMP_ERRS

    # 结束
    退出 $EXIT_CODE

  • 如果将 "|tee..." 放在 "done" 之后,这可以提高效率。 (2认同)