bash:stderrを赤色で印刷します


123

bashにstderrメッセージを赤色で表示させる方法はありますか?


4
bashは出力を色付けしないと思います。一部のプログラムは何かを解析したい場合があり、色付けはエスケープされたシーケンスでデータを台無しにします。GUIアプリは色を処理するはずです。
kolypto 09

BalázsPozsárとkilldash9の答えを組み合わせることで、鮮明になります: function color { "$@" 2> >(sed $'s,.*,\e[31m&\e[m,') } bashとzshで動作します。これを回答のb / cレピュテーションとして追加することはできません。
ハインリッヒハートマン

1
これを行うためにbashを変更する答えを待っています。以下の解決策はすべて、実際にはstderrを変更し、場合によってはstdoutでそれを並べ替えることもあります。
masterxilo

回答:


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

6
すばらしいです!しかし、私はそれを永続化する方法があるのだろうか:)
kolypto 09

9
素晴らしいヒント!提案:>&2直前; done)に追加することにより、stderr向けの出力は実際にはstderrに書き込まれます。プログラムの通常の出力をキャプチャする場合に役立ちます。
ヘンコ

8
以下はを使用しておりtput、私の意見では少し読みやすくなっています。command 2> >(while read line; do echo -e "$(tput setaf 1)$line$(tput sgr0)" >&2; done)
Stefan Lasiewski

2
各出力行に対して2つのtputプロセスを実行することは、まったくエレガントではないと思います。たぶん、変数にtputコマンドの出力を保存し、それらを各エコーに使用するとします。しかし、再び、読みやすさは本当に良くありません。
バラスポッサル14年

1
この解決策は空白を保存しませんが、簡潔にするために気に入っています。 IFS= read -r line役立つはずですが、しません。理由はわかりません。
マックスマーフィー

89

方法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—これは、出力が別のコマンドにパイプされるコマンドのエラー戻りコードを保持するシェルオプションです。これは、外側のシェルのpipefailオプションを変更しないように、括弧で作成されたサブシェルで行われます。
  • "$@"—新しいコマンドとして関数の引数を実行します。 "$@"に等しい"$1" "$2" ...
  • 2>&1-リダイレクトstderrにコマンドのをstdout、それがなるようsedさんstdin
  • >&3—の省略形で1>&3、これstdoutは新しい一時ファイル記述子にリダイレクトします3。 後で3ルーティングされますstdout
  • sed ...—上記のリダイレクトのため、sed's stdinstderr実行されたコマンドのものです。その機能は、各行をカラーコードで囲むことです。
  • $'...' バックスラッシュでエスケープされた文字を理解させるbashコンストラクト
  • .* —行全体に一致します。
  • \e[31m —次の文字を赤にするANSIエスケープシーケンス
  • &sed一致した文字列全体(この場合は行全体)に展開する置換文字。
  • \e[m —色をリセットするANSIエスケープシーケンス。
  • >&2-の略記1>&2、これはリダイレクトsedさんstdoutstderr
  • 3>&1-一時的なファイルディスクリプタをリダイレクト3バックにstdout

9
+1ベストアンサー!絶対に過小評価されています!
muhqu

3
素晴らしい答えとさらに良い説明
ダニエルセロディオ14年

なぜ追加のリダイレクトをすべて行う必要があるのですか?やり過ぎのようです
-qodeninja

1
それを動作させる方法はありzshますか?
エイアルレビン

1
ZSHは、簡略化されたリダイレクトフォームを認識しません。それには、さらに2つの1が必要です。すなわち、zsh: color()(set -o pipefail;"$@" 2>&1 1>&3|sed $'s,.*,\e[31m&\e[m,'1>&2)3>&1
-Rekin

26

また、stderredをチェックアウトすることもできますhttps : //github.com/sickill/stderred


うわー、このユーティリティは素晴らしいです、それを必要とする唯一のことは、それを有効にするためにそれ以上の作業をすることなく、1行ですべてのユーザーのためにそれをインストールするaptリポジトリを持つことです。
ソリン

別の端末でビルドスクリプトを使用してテストしたときにうまく機能するように見えましたが、グローバルに(で.bashrc)使用することにためらっています。でもありがとう!
ジョエルプラ

2
OS X El Capitanでは、これが動作する方法(DYLD_INSERT_LIBRARIES)は、SIPで保護されているため、システムバイナリで「壊れています」。そのため、他の回答に記載されているbashオプションを使用した方がよい場合があります。
hmijail

1
@hmijail for MacOSはgithub.com/sickill/stderred/issues/60に従ってください。回避策を見つけることができます。部分的な回避策は既に存在しますが、少しバグがあります。
ソリン

15

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

以前にこれを投稿しました:STDOUTとSTDERRのフォントの色を設定する方法



1
これが圧倒的なベストアンサーです。インストールやsudo特権を必要とせずに簡単に実装でき、すべてのコマンドに一般化できます。
ルークデイビス

1
残念ながら、これはコマンドチェーン(command && nextCommand || errorHandlerCommand)ではうまく機能しません。エラー出力は、errorHandlerCommand出力の後に続きます。
carlin.scott

1
同様に、これをsource ~/.bashrc2回使用すると、基本的に端末がロックします。
ドルフ

@Dolf:私のbashrcでは、このコードがリロードされないように、ifステートメントで周囲を簡単にガードします。それ以外の場合、問題はリダイレクトがすでに行われた後のリダイレクト「exec 9>&2」です。> 2が元々指し示していた場所がわかっている場合は、おそらく定数に変更してください。
ゴスペル


7

BalázsPozsárの答えを純粋なbashで実装するラッパースクリプトを作成しました。$ PATHおよびprefixコマンドに保存して、出力を色分けします。

    #!/ bin / bash

    if [$ 1 == "--help"]; それから
        echo「コマンドを実行し、発生したすべてのエラーを色付けします」
        echo "例:` basename $ {0} `wget ..."
        echo "(c)o_O Tync、ICQ#1227-700、お楽しみください!"
        出口0
        fi

    #すべてのエラーをキャッチする一時ファイル
    TMP_ERRS = $(mktemp)

    #コマンドを実行
    "$ @" 2>>(行の読み取り中; do echo -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 ===エラー=== \ e [0m"
        猫$ TMP_ERRS
        fi
    rm -f $ TMP_ERRS

    #終了
    $ EXIT_CODEを終了


2
これは、「完了」の後に「| tee ...」を置くとより効率的になります。
ジュリアーノ

3

このような関数を使用できます


 #!/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

>&2を追加してstderrに出力します


4
問題に取り組んでいない。あなたはOPが興味あるものである標準出力、標準エラー出力から分離する方法を提供していない。
ジェレミー・フィッセル

1

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

このソリューションは私のために働いた:https : //superuser.com/questions/28869/immediately-tell-which-output-was-sent-to-stderr

私はこの関数を.bashrcorに入れました.zshrc

# Red STDERR
# rse <command string>
function rse()
{
    # We need to wrap each phrase of the command in quotes to preserve arguments that contain whitespace
    # Execute the command, swap STDOUT and STDERR, colour STDOUT, swap back
    ((eval $(for phrase in "$@"; do echo -n "'$phrase' "; done)) 3>&1 1>&2 2>&3 | sed -e "s/^\(.*\)$/$(echo -en \\033)[31;1m\1$(echo -en \\033)[0m/") 3>&1 1>&2 2>&3
}

次に、例えば:

$ rse cat non_existing_file.txt

赤い出力が表示されます。


リダイレクト終了コードのset -o pipefail;(evalに追加できます
kvaps

また"、引数にスペースを保持するためにevalを追加します
kvaps


0

fifoを使用したバージョン

mkfifo errs
stdbuf -o0 -e0 -i0 grep . foo | while read line; do echo -e "\e[01;31m$line  \e[0m" >&2; done &
stdbuf -o0 -e0 -i0 sh $script 2>errs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.