题 bash:打印红色的stderr


有没有办法进行bash显示 标准错误 红色的消息?


97
2017-08-26 21:10




我猜bash永远不会给它的输出着色:某些程序可能想要解析一些东西,而着色会破坏带有转义序列的数据。我想,GUI应用程序应该处理颜色。 - kolypto
结合BalázsPozsár和killdash9的答案给出了清晰: function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') }  适用于bash和zsh。无法添加此作为答案b / c声誉。 - Heinrich Hartmann
我正在等待修改bash的答案来做到这一点。解决方案如下 其实 修改stderr甚至可能重新排序w.r.t.当必须保留stderr的确切字节序列时,stdout会破坏事物,例如管道时。 - masterxilo


答案:


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

84
2017-08-26 21:39



大!但我想知道是否有办法让它永久:) - kolypto
棒极了!建议:加入 >&2 就在之前 ; done),stderr的输出实际上是写入stderr的。如果您想捕获程序的正常输出,这将非常有用。 - henko
以下用途 tput,在我看来稍微更具可读性: command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done) - Stefan Lasiewski
我认为为每个输出行执行2个输出过程根本不优雅。也许你将tput命令的输出存储在一个变量中,并为每个echo使用它们。但话说回来,可读性并不是更好。 - Balázs Pozsár
这个解决方案不保留空白,但我喜欢它的简洁。 IFS= read -r line 应该帮助但不是。不知道为什么。 - Max Murphy


方法1:使用流程替换:

command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)

方法2:在bash脚本中创建一个函数:

color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1

像这样用它:

$ color command

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

继续阅读有关方法2如何工作的解释。此命令演示了一些有趣的功能。

  • color()...  - 创建一个名为color的bash函数。
  • set -o pipefail  - 这是一个shell选项,用于保存输出通过管道输入另一个命令的命令的错误返回码。这是在子shell中完成的,子shell由括号创建,以便不更改外壳中的pipefail选项。
  • "$@"  - 作为新命令执行函数的参数。 "$@" 相当于 "$1" "$2" ...
  • 2>&1  - 重定向 stderr 的命令 stdout 这样它就变成了 sedstdin
  • >&3  - 简写 1>&3,这重定向 stdout 到一个新的临时文件描述符 33 被送回去了 stdout 后来。
  • sed ...  - 由于上面的重定向, sedstdin 是个 stderr 执行的命令。它的功能是用颜色代码包围每一行。
  • $'...' 一个bash结构,使它能理解反斜杠转义的字符
  • .*  - 匹配整条线。
  • \e[31m  - ANSI转义序列,导致以下字符为红色
  • &  - sed 替换扩展为整个匹配字符串的字符(在本例中为整行)。
  • \e[m  - 重置颜色的ANSI转义序列。
  • >&2  - 简写 1>&2,这重定向 sedstdout 至 stderr
  • 3>&1  - 重定向临时文件描述符 3 回到 stdout

72
2018-04-23 20:53



+1最佳答案!绝对被低估了! - muhqu
很好的答案,甚至更好的解释 - Daniel Serodio
为什么需要进行所有额外的重定向?看起来有点矫枉过正 - qodeninja
@qodeninja说明给出了重定向的目的。如果你能找到一种更简单的方法,我很乐意看到它! - killdash9
有没有办法让它发挥作用 zsh? - Eyal Levin


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


23
2017-12-13 21:40



哇,这个实用程序很棒,它唯一需要的是拥有一个apt存储库,可以为所有用户安装它,只需一行,而不需要做更多工作来启用它。 - sorin
当我在一个单独的终端中使用构建脚本测试它时,似乎工作得很好,但是我对在全局使用它感到犹豫(在 .bashrc)。谢谢! - Joel Purra
在OS X El Capitan中,它的工作方式(DYLD_INSERT_LIBRARIES)在系统二进制文件中被“破坏”,因为它们受SIP保护。因此,最好使用其他答案中给出的bash选项。 - hmijail
@hmijail for MacOS请关注 github.com/sickill/stderred/issues/60 所以我们可以找到一个解决方法,一个部分已经存在,但有点儿马车。 - sorin


http://sourceforge.net/projects/hilite/


14
2017-08-26 21:18





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;'

我以前发过这个帖子: 如何设置STDOUT和STDERR的字体颜色


11
2018-01-29 08:49



有关: unix.stackexchange.com/questions/367636/... - Blauhirn
到目前为止,这是最好的答案;无需安装/需要sudo权限即可轻松实现,并且可以推广到所有命令。 - Luke Davis
不幸的是,这不适用于命令链(命令&& nextCommand || errorHandlerCommand)。错误输出在errorHandlerCommand输出之后。 - carlin.scott
同样,如果我 source ~/.bashrc 两次这个,我的终端基本上锁定了。 - Dolph
@Dolf:在我的bashrc中,我可以使用周围的if语句轻松防范这种情况,以防止此代码重新加载。否则,问题是重定向已经发生后重定向'exec 9>&2'。如果您知道> 2指向最初的位置,也许可以将其更改为常量。 - gospes


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


    #!/斌/庆典

    如果[$ 1 ==“ -  help”];然后
        echo“执行命令并着色所有发生的错误”
        echo“示例:`basename $ {0}`wget ...”
        echo“(c)o_O Tync,ICQ#1227-700,Enjoy!”
        退出0
        科幻

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

    #执行命令
    “$ @”2 >>(读取行时;做回声-e“\ e [01; 31m $ line \ e [0m”| tee --append $ TMP_ERRS; done)
    EXIT_CODE = $?

    #再次显示所有错误
    if [-s“$ TMP_ERRS”];然后
        echo -e“\ n \ n \ n \ e [01; 31m === ERRORS === \ e [0m”
        cat $ TMP_ERRS
        科幻
    rm -f $ TMP_ERRS

    #完成
    退出$ EXIT_CODE


7
2017-08-26 22:13



如果在“完成”之后放置“| tee ...”,则可以提高效率。 - Juliano


你可以使用这样的功能


 #!/bin/sh

color() {
      printf '\033[%sm%s\033[m\n' "$@"
      # usage color "31;5" "string"
      # 0 default
      # 5 blink, 1 strong, 4 underlined
      # fg: 31 red,  32 green, 33 yellow, 34 blue, 35 purple, 36 cyan, 37 white
      # bg: 40 black, 41 red, 44 blue, 45 purple
      }
string="Hello world!"
color '31;1' "$string" >&2


3
2017-08-26 22:29



没有解决问题。你还没有提供一种将stderr与stdout分开的方法,这正是O.P.感兴趣的。 - Jeremy Visser


我有一个稍微修改过的O_o Tync脚本版本。我需要为OS X Lion制作这些mod并且它并不完美,因为脚本有时会在包装命令之前完成。我加了一个睡眠,但我确信有更好的方法。

#!/bin/bash

   if [ $1 == "--help" ] ; then
       echo "Executes a command and colorizes all errors occured"
       echo "Example: `basename ${0}` wget ..."
       echo "(c) o_O Tync, ICQ# 1227-700, Enjoy!"
       exit 0
       fi

   # Temp file to catch all errors
   TMP_ERRS=`mktemp /tmp/temperr.XXXXXX` || exit 1

   # Execute command
   "$@" 2> >(while read line; do echo -e "$(tput setaf 1)$line\n" | tee -a $TMP_ERRS; done)
   EXIT_CODE=$?

   sleep 1
   # Display all errors again
   if [ -s "$TMP_ERRS" ] ; then
       echo -e "\n\n\n$(tput setaf 1) === ERRORS === "
       cat $TMP_ERRS
   else
       echo "No errors collected in $TMP_ERRS"
   fi
   rm -f $TMP_ERRS

   # Finish
   exit $EXIT_CODE

1
2018-06-08 17:37