コマンドは{ echo err >&2; echo out >&1; } | :
「err」を印刷できますが、2番目のコマンドは印刷できないのはなぜですか?
コンテナのいくつかのテスト:
- ダーバン:11.5(バッシュ/5.1.4)
- ロッキーLinux:9.0(バッシュ/5.1.8)、
- 中央オペレーティングシステム:1908年7月7日(bash/4.2.46)、
- CentOS: 8.4.2105(bash/4.4.19)。
これはホストCentOS 8.0.1905、Debian 11.4でも発生します。
~# { echo err >&2; echo out >&1; } | :
err
~# { echo out >&1; echo err >&2; } | :
~#
以下を使用しない:
ことが正しいようです。
~# { echo out >&1; echo err >&2; } | sed 's/.*/-&-/'
err
-out-
~#
ただし、他のホストCentOS 7.7.1908(bash / 4.2.46)では、次のように印刷されます。
~# { echo out >&1; echo err >&2; } | :
err
~#
答え1
間の違い
{ echo err >&2; echo out >&1; } | :
...そして
{ echo out >&1; echo err >&2; } | :
echo
...2つの呼び出しが行われた順序です。順序は進行方法によって重要です。早く最初のecho
実行が可能です。
パイプの両側は同時に開始され、{ ...; }
標準入力ストリームから読み込まれません。これは、パイプラインが終了するとすぐにすぐに削除されることを意味します。:
:
:
echo out >&1
パイプが解体されると、書き込むパイプバッファはありません。存在しないパイプに書き込もうとすると、echo
パイプの左側がPIPE信号を受けて死にます。
実行前に終了するとecho err >&2
出力はありません。
だから:
パイプの状態は考慮されていないため、常に
err
出力が得られます。{ echo err >&2; echo out >&1; } | :
echo err >&2
err
時には次のような結果が出力されます。{ echo out >&1; echo err >&2; } | :
~によると:
以前に終了した場合でもecho out >&1
実行する機会があります。最初に終了すると、:
左が早期に終了するため、出力はありません。
私の考えでは、ほとんどの人はほとんどのシステムで2番目のパイプの非晶質の動作を経験しません。それにもかかわらず、これを示すオペレーティングシステムとシェルバージョンの組み合わせを見つけることができます。また、単一のシェルセッション内でもFreeBSDの非決定的な動作を複製しましたzsh
(シェルが他の動作よりも1つの動作を好むように見えましたが、最終的に移行を確認するまで10回以上試みる必要がありました)。
答え2
(まず、何かを試していますが、それがどのように機能し、何をしているのかわからない場合は、ログインした状態でその操作を中止することをお勧めします。root
)
{ echo err >&2; echo out >&1; } | :
これは文字列をエコーし、err\n
その文字列を含む標準出力を標準エラー(ターミナルに表示)にリダイレクトし、次に文字列を標準出力にエコーしてout\n
標準出力にリダイレクトします。その後、標準出力が次にパイプされます。標準入力では:
何も出力しません。
追加テスト:
$ { echo err >&2; echo out >&1; } 1> outputfile 2> errorfile
$ for file in *; do echo $file; cat $file; done
errorfile
err
outputfile
out
$ rm errorfile outputfile
$ { echo err >&2; echo out >&1; } 1> outputfile 2> errorfile
$ for file in *; do echo $file; cat $file; done
errorfile
err
outputfile
out
しかし、場合によっては、標準エラーが原因で出力が失われるように見える理由がわからない場合があります。私はこれを再現できません:
$ { echo err >&2; echo out >&1; } | :
err
$ { echo out >&1; echo err >&2; } | :
err