stderrに出力するエコー


1116

エコーのように動作するが、標準出力ではなく標準エラー出力に出力する標準のBashツールはありますか?

私にはできることはわかっていますecho foo 1>&2が、少し醜く、間違いが起こりやすいと思います(たとえば、状況が変わったときに誤って編集される可能性が高くなります)。


回答:


1454

これを行うと、読みやすくなります。

>&2 echo "error"

>&2ファイル記述子#2をファイル記述子#1にコピーします。したがって、このリダイレクトが実行された後、両方のファイル記述子は同じファイルを参照します。1つのファイル記述子#2は元々参照されていました。詳細については、「Bash Hackers Illustrated Redirection Tutorial」を参照してください。


2
私はかなり前にこのトリックを学びました。このページにはいくつかの良い情報があります。tldp.org/LDP/abs/html/io-redirection.html
Marco Aurelio

46
@BCS aliasシェルスクリプトでの使用については知りません。おそらく安全に使用できるでしょうerrcho(){ >&2 echo $@; }
Braden Best

3
>&2は通常、最後に置かれます。これは機能しますが、あまり使用されません
Iskren Ivov Chernev

159
私がUnixライクなシステムを使用していた40年近くの間、リダイレクトを最後以外のどこにでも置くことができるとは思いもしませんでした。このように前に置くと、より明確になります(または@MarcoAurelioが言うように「読みやすくなります」)。何か新しいことを教えてくれた+1。
ヘファイストス2015年

参考までに:単に文字列をエコーする以外にフォーマットまたは何かしたい場合は、リダイレクトを最後に戻す必要があります。たとえば、errcho(){ >&2 echo $@|pr -To5;}動作しません。:あなたのような最後のパイプの後にリダイレクトどこかに置く必要があるでしょうそのような何かをするにはerrcho(){ echo $@|>&2 pr -To5;}
ジョン・レッド

423

あなたは関数を定義することができます:

echoerr() { echo "$@" 1>&2; }
echoerr hello world

これはスクリプトよりも高速で、依存関係はありません。

Camilo Martinのbash固有の提案は「ヒア文字列」を使用し、echoが通常飲み込む引数(-n)を含め、渡したものをすべて出力します。

echoerr() { cat <<< "$@" 1>&2; }

グレン・ジャックマンの解決策はまた、議論を飲み込む問題を回避します。

echoerr() { printf "%s\n" "$*" >&2; }

7
エコーはちょっと信頼できないと言わざるを得ません。echoerr -ne xt「-ne xt」は出力されません。printfそのためのより良い使用。
Camilo Martin

10
ああ、あなたも猫を実際に使うことができます:echoerr() { cat <<< "$@" 1>&2; }
カミロ・マーティン

2
知らなかった。追加しました。
James Roth

4
またはprintf "%s\n" "$*" >&2
glenn jackman

4
@GKFXもちろん、引用する場合にのみ正しく機能します。なぜ人々が文字列を引用しないのかは私を超えています。(引用符を付けない場合、1つ以上の$IFS空白で区切られたすべてが個別の引数として送信されます。これは、sでechoそれらを連結する手段の場合ですが、引用符を付けないこと0x20の危険性は、入力する2文字少ないことの利便性をはるかに上回ります) 。
Camilo Martin

252

1は標準出力なので、次のように出力リダイレクトの前に明示的に名前を付ける必要はありません。>代わりに次のように入力できます。

echoこのメッセージはstderrに送られます>&2

1>&2確実に入力するのが難しいのではないかと心配しているように思われるので、冗長なものを削除1することで、少し励まされるかもしれません。


59

別のオプション

echo foo >>/dev/stderr

4
このオプションはポータブルですか?これが一部のUNIXフレーバーで機能しないかどうか誰かが知っていますか?
Dacav 2014

7
/ dev / stderrにアクセスできない特定のchrootでは機能しません。
ザカリーヴァンス

12
この行を実行するスクリプトがいる場合-のは、それを呼びましょうfoo-例えば-独自の標準エラー出力がリダイレクトされているfoo >foo.log 2>&1-そして、echo foo >/dev/stderrその前にすべての出力を壊します。 >>代わりに使用してください:echo foo >>/dev/stderr
doshea

同様に、あなたは持ってい/dev/fd/2ます。
jbruni 2016

@Dacavこれは確かに移植可能です:/proc/self/fd/2。以下の私の回答を参照してください:)
セバスチャン

31

いいえ、それが標準的な方法です。エラーの原因にはなりません。


9
エラーの原因はなりませんが、エラーが発生する可能性が高くなります。OTOHそれはそれほど大きな問題ではありません。
BCS

6
@Mike DeSimone:他の誰かがコードをいじったり、出力をシャッフルしたり、実際にbashを知らなかったりすると、簡単にをドロップ(またはタイプミス)する可能性があり1>&2ます。私たちは皆、これが起こらないことを望みますが、私たち全員がそれが起こる場所であったと確信しています。
Cascabel

2
( echo something 1>&2 ; something else ) > log-> (echo something; cp some junk 1>&2 ; something else) > logおっと。
BCS

29
私見、誰かがコードをいじって、bashを知らないなら、これはあなたの問題の中で最も少ないかもしれません。
Mike DeSimoneが2010年

7
それが問題になりそうな場合は、別の言語を使用することから始めるべきだと思います。
2010年

17

メッセージをsyslogに記録してもかまわない場合、not_so_uglyの方法は次のとおりです。

logger -s $msg

-sオプションは、「メッセージを標準エラーおよびシステムログに出力する」という意味です。


1
これは素晴らしい!それはどれくらいポータブルですか?
code_monk

@code_monk:loggerコマンドは、IEEE STD 1003.2(「POSIX.2」)互換性があると予想され、loggerコマンドは、UTIL-linuxパッケージの一部であり、Linuxカーネルのアーカイブ⟨から入手可能ですkernel.org/pub/linux/utils / util- linux⟩。
ミク

12

これは単純なSTDERR関数で、パイプ入力をSTDERRにリダイレクトします。

#!/bin/bash
# *************************************************************
# This function redirect the pipe input to STDERR.
#
# @param stream
# @return string
#
function STDERR () {

cat - 1>&2

}

# remove the directory /bubu
if rm /bubu 2>/dev/null; then
    echo "Bubu is gone."
else
    echo "Has anyone seen Bubu?" | STDERR
fi


# run the bubu.sh and redirect you output
tux@earth:~$ ./bubu.sh >/tmp/bubu.log 2>/tmp/bubu.err

2
エイリアスを使用して同じことを実行し、はるかにコンパクトにすることができると思います
BCS

または、デバイスファイルに直接パイプすることもできますecho what | /dev/stderr...
ardnew

11

注:私は、誤解を招く/あいまいな「stderrに出力するエコー」質問ではなく、ポストに回答しています(OPによって既に回答されています)。

関数を使用して意図を示し、必要な実装を調達します。例えば

#!/bin/bash

[ -x error_handling ] && . error_handling

filename="foobar.txt"
config_error $filename "invalid value!"

output_xml_error "No such account"

debug_output "Skipping cache"

log_error "Timeout downloading archive"

notify_admin "Out of disk space!"

fatal "failed to open logger!"

そしてerror_handling存在:

ADMIN_EMAIL=root@localhost

config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; }

output_xml_error() { echo "<error>$*</error>" 2>&1; }

debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; }

log_error() { logger -s "$*"; }

fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; }

notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; }

OPの懸念を処理する理由:

  • 可能な限り素晴らしい構文(醜い記号の代わりに意味のある単語)
  • エラーが発生しにくい(特にスクリプトを再利用する場合)
  • それは標準のBashツールではありませんが、あなたやあなたの会社/組織の標準的なシェルライブラリになることができます

その他の理由:

  • 明快さ-他のメンテナに意図を示します
  • 速度-関数はシェルスクリプトよりも高速です
  • 再利用性-関数は別の関数を呼び出すことができます
  • 構成可能性-元のスクリプトを編集する必要はありません
  • デバッグ-エラーの原因となっている行を簡単に見つけることができます(特に、大量のリダイレクト/フィルタリング出力でデッドリングしている場合)
  • 堅牢性-関数が欠落していてスクリプトを編集できない場合は、同じ名前の外部ツールの使用にフォールバックできます(たとえば、log_errorはLinuxのロガーにエイリアス化できます)
  • 実装の切り替え-ライブラリの「x」属性を削除することにより、外部ツールに切り替えることができます
  • 出力不可-STDERRまたは他の場所に移動するかどうかを気にする必要がなくなりました
  • パーソナライズ-環境変数で動作を設定できます

10

私のおすすめ:

echo "my errz" >> /proc/self/fd/2

または

echo "my errz" >> /dev/stderr

echo "my errz" > /proc/self/fd/2効果的に出力は以下となりますstderrので/proc/self、現在のプロセスへのリンクです、そして/proc/self/fdプロセス開かれたファイル記述子を保持し、その後、01、および2のために立ってstdinstdoutそしてstderrそれぞれ。

/proc/selfリンクは、MacOSの上では動作しません、しかし、/proc/self/fd/*Android上でTermuxで提供されていますが、ありません/dev/stderrBashスクリプトからOSを検出する方法は?使用するバリアントを決定することにより、スクリプトをよりポータブルにする必要がある場合に役立ちます。


5
/proc/self私はもっと素直に固執ますのでリンクは、MacOSの上で作業をしない/dev/stderr方法。また、他の回答/コメントに記載されているように>>、追加に使用することをお勧めします。
MarkHu 2017年

4
/proc/self/fd/*AndroidのTermuxで利用できますが、では利用できません/dev/stderr
go2null 2018

9

catここで言及されているものは使用しないでください。catプログラムechoありprintf、bash(シェル)ビルトインです。プログラムまたはその他のスクリプト(上記でも説明)を起動すると、すべてのコストを伴う新しいプロセスが作成されます。組み込み関数を使用すると、プロセス(-environment)を作成(実行)する必要がないため、関数の記述が非常に安価になります。

opnerは、「stderr に出力(パイプ)するための標準的なツールはありますか」と尋ねます。...パイプの再リダイレクトは、unix(Linux ...)やbash(sh)などのシステムでの基本的な概念であり、これらの概念に基づいています。

&2>1はこのような記法でリダイレクトすることはオープナーに同意します:現代のプログラマーにとってはあまり快適ではありませんが、それはバッシュです。Bashは巨大で堅牢なプログラムを作成するためのものではなく、管理者が少ないキー操作で作業できるようにするためのものです;-)

そして、少なくとも、行のどこにでもリダイレクトを配置できます。

$ echo This message >&2 goes to stderr 
This message goes to stderr

1
パフォーマンス上の理由だけでプログラムを使用しないように開発者に伝えることは、時期尚早の最適化です。エレガントでわかりやすいアプローチは、理解しにくいコードよりもパフォーマンスが良い(ミリ秒のオーダー)よりも優先する必要があります。
-GuyPaddock

@GuyPaddock申し訳ありませんが、これを正しく読んでいません。もみ; そのbashでうまく処理されるパイプのリダイレクトについてです。bashがリダイレクトする(醜い)構文が気に入らない場合は、bashスクリプトの実装を停止するか、bashの方法を学ぶ必要があります。第二; bashビルトインと呼ばれるのに比べて、新しいプロセスを起動するのにどれほど費用がかかるかを知っておく必要があります。
return 42 '18

1
Bashビルトインのパフォーマンスのトレードオフを誰かに知らせることと、cat遅いのでcatを使用しないように誰かに指示することには違いがあります。猫が正しい選択である無数のユースケースがあるので、私はあなたの答えに反対する理由です。
GuyPaddock

@GuyPaddockオープナーはecho交換を求めた。cat彼がを使用する場合でも、bashリダイレクトを使用する必要があります。とにかく。したがって、catここで使用する意味はまったくありません。ちなみに私はcat1日100回使用していますが、オープナーが要求したコンテキストではありません...
リターン42

8

私が最近つまずいた別のオプションはこれです:

    {
        echo "First error line"
        echo "Second error line"
        echo "Third error line"
    } >&2

これはBashビルトインのみを使用し、複数行のエラー出力をエラーが発生しにくくします(&>2すべての行に追加することを覚えておく必要がないため)。


1
信じられません、私がbash-redirectを使用することをお勧めするとき、あなたは私に投票し、あなた自身の答えではbash-redirectを使用しています。
リターン42

1
@ return42私はあなたの答えに投票しました。なぜならそれはすべて、OPに彼らが始めたものより良い答えはないということを伝えただけだったからです。それは実際には答えではありません。私はあなたの答えにサブシェルの提案も見ていません...あなたの答えは本当にOPを使わないようにアドバイスするcatか、他のユーティリティを助言するだけで、それは質問に対してトピック外です。
GuyPaddock


6

read stderrに出力するシェル組み込みコマンドであり、リダイレクトトリックを実行せずにエコーのように使用できます。

read -t 0.1 -p "This will be sent to stderr"

これ-t 0.1は、読み取りの主な機能を無効にするタイムアウトであり、stdinの1行を変数に格納します。


5
OS XのBashは「0.1」を許可していません
James Roth

2

スクリプトを作成する

#!/bin/sh
echo $* 1>&2

それはあなたのツールになるでしょう。

または、スクリプトを個別のファイルに含めたくない場合は、関数を作成します。


6
関数にすること(ジェームス・ロスの答えのように)に優れ、最初の引数だけでなく、すべての引数を渡す方が良いでしょう。
Cascabel

2
なぜ関数はより良いのでしょうか?(または、代わりに:「なぜそれがより良いのかを説明する方がいい...」)
Ogre Psalm33 '20

3
@ OgrePsalm33関数が優れている理由の1つは、スクリプトを呼び出すときに、通常、新しいシェルインスタンスが作成され、スクリプトを実行する環境を提供することです。一方、関数は現在実行中のシェルの環境に配置されます。この場合、関数の呼び出しは、シェルの別のインスタンスの作成が回避されるため、はるかに効率的な操作になります。
デステンソン、2015

-10

Mac OS X:受け入れられた回答と他のいくつかの回答を試しましたが、すべてMacでSTDERRではなくSTDOUTと書きました。

Perlを使用して標準エラーに書き込む移植可能な方法を次に示します。

echo WARNING! | perl -ne 'print STDERR'

LOLあなたが望むすべてを反対投票しますが、これは私が実際に私のコードで使用する解決策です!
Noah Sussman
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.