一部のLinuxプログラムの出力がSTDOUTとSTDERRのどちらにも出力されないのはなぜですか?


21

一部のLinuxプログラムの出力がSTDOUTとSTDERRのどちらにも出力されないのはなぜですか?

実際、使用する「ストリーム」に関係なく、すべてのプログラム出力を確実にキャプチャする方法を知りたいです。私が抱えている問題は、一部のプログラムが出力をキャプチャさせないように見えることです。

例は「time」コマンドです。

time sleep 1 2>&1 > /dev/null

real        0m1.003s
user        0m0.000s
sys         0m0.000s

または

time sleep 1 &> /dev/null

real        0m1.003s
user        0m0.000s
sys         0m0.000s

両方の時間に出力が表示されるのはなぜですか?すべてが/ dev / nullにパイプされると予想しました。

どの出力ストリームを使用していますか?また、どのようにファイルにパイプできますか?

問題を回避する1つの方法は、たとえば次のコマンドを含むBashスクリプトを作成することですcombine.sh

$@ 2>&1

次に、「時間」の出力を正しい方法でキャプチャできます。

combine.sh time sleep 1 &> /dev/null

(出力が表示されない-正しい)

別の結合スクリプトを使用せずに、私が望むものを達成する方法はありますか?


3
最初に順序を逆にする必要があります。2>&1 > /dev/nullつまり、「2は1に移動します(つまり、デフォルトでは端末)、1は/ dev / nullに移動します(ただし2はまだ端末に移動します!)。>/dev/null 2>&1」 「1は/ dev / nullに移動し、2は1の移動先に移動します(つまり、/ dev / nullにも移動します)。組み込みの「時間」はリダイレクトされないため、ここではまだ機能しませんが、より一般的には正しいです(たとえば、/ usr / bin / timeを使用すると機能します)。1に行かない2として、2に1の「方向」をコピーして考えてみて「2>&1」
オリヴィエ・デュラック

回答:


38

この質問はBashFAQ / 032で対処されています。あなたの例では:

{ time sleep 1; } 2> /dev/null

理由

time sleep 1 2>/dev/null

その構文で、あなたがしたいと思うので、どのようにあなたが期待している動作しないtimeコマンドsleep 1 2>/dev/null(はい、コマンドsleep 1標準エラー出力はにリダイレクト/dev/null)。timeこれを実際に可能にするために、ビルトインはそのように動作します。

bash 組み込みがうまく、それは組み込みだから...実際にこれを行うことができます。このような動作は、time通常はにある外部コマンドでは不可能/usr/binです。確かに:

$ /usr/bin/time sleep 1 2>/dev/null
$

さて、あなたの質問への答え

一部のLinuxプログラムの出力がSTDOUTにもSTDERRにもならないのはなぜですか?

つまり、出力はstdoutまたはstderrに送られます。

お役に立てれば!


2
他のfdを作成し、コマンドを明示的にそれらに移動させることができます(例:bashスクリプト: exec 3>/some/file ; ls >&3 ;
オリビエデュラック

@OlivierDulac確かに、またはcoproc組み込みでさらにシンプルに。しかし、time組み込みの場合はそうではありません。
gniourf_gniourf

@ gniourf-gniourf:「出力はstdoutまたはstderrに送られます」という文のためにコメントしていました^^
オリビエデュラック

14

あなたの特定の質問time組み込みが回答されているが、そこにあるのいずれかに書いていないいくつかのコマンドstdoutまたはにはstderr。典型的な例はUnixコマンドcryptです。 crypt引数なしstdinでは、標準入力を暗号化し、標準出力に書き込みますstdout。を使用してパスワードの入力をユーザーにgetpass()要求し/dev/ttyます。デフォルトでは、にプロンプ​​トが出力されます。 /dev/tty現在の端末デバイスです。へ/dev/ttyの書き込みには、現在の端末への書き込みの効果があります(ある場合は、を参照isatty())。

crypt書き込みできない理由stdoutは、暗号化された出力をに書き込むためstdoutです。また、ユーザーがをリダイレクトした場合にプロンプ​​トが表示されるよう/dev/ttyに、書き込みをstderr行う代わりにプロンプ​​トを表示することをお勧めします。(同じ理由で、暗号化するデータの読み取りに使用されているため、からパスワードを読み取ることができません。)stdoutstderrcryptstdin


2
+1。OPにはあまり関係がありませんが、出会うすべての人にはより関連があります。Google経由。:-)
ruakh

0

time sleep 1 > /dev/null 2>&1#「sleep」の出力をリダイレクトしてnullにします。次に、「time」はリダイレクトなしで独自の出力を書き込みます。「time (sleep 1 > /dev/null 2>&1)」のようなものです。

(time sleep 1) > /dev/null 2>&1 #「time sleep 1」を実行し、その出力をnullにリダイレクトします。

[] s


-1

あなたの場合の問題は、リダイレクトが別の方法で機能することです。あなたが書いた

time sleep 1 2>&1 > /dev/null

これにより、標準出力が/dev/nullリダイレクトされ、標準エラーが標準出力にリダイレクトされます。

すべての出力をリダイレクトするには、書く必要があります

time sleep 1 > /dev/null 2>&1 

次に、標準エラーが標準出力にリダイレクトされ、その後、すべての標準出力(標準エラーを含む)がにリダイレクトされ/dev/nullます。


これはbash builtin では機能しませんtime。いくつかの説明については私の答えをご覧ください。
gniourf_gniourf

これは同様の質問に対する有用な回答であるため、+ 1。@Olivierは上記の質問へのコメントでそれをより良く説明していますが。
ウィルシェパード14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.