Bashリダイレクトの構文とその出力を理解してください。

Bashリダイレクトの構文とその出力を理解してください。

私はLinuxに初めてアクセスし、リダイレクトがどのように機能するかを理解しようとしています。

同じファイルにリダイレクトするためのさまざまな構文をテストしましたが、すべて同じ結果を生成するわけではありませんstdoutstderr

file1たとえば、存在しない2つのファイル(およびfile2)と2つのファイル(fooおよびfz)を一覧表示しようとすると、次のようになります。

文法#1(リダイレクトなし):

$ ls file1 foo fz file2

これは端末から得られる出力です。

ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo  fz

構文#2:

今リダイレクトを通して:

$ ls file1 foo fz file2 > redirect 2>&1

このredirectファイルには構文#1と同じ結果が含まれています。

ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz

したがって、上記の両方の構文はシェルがstderr最初に印刷され、次にstdout

構文#3:

次の構文のいずれかを使用しようとすると、次のようになります。

$ ls file1 foo fz file2 > redirect 2> redirect

または

$ ls file1 foo fz file2 2> redirect > redirect

これにより、ファイルredirectには次の内容が含まれます。

foo
fz
nnot access file1: No such file or directory
ls: cannot access file2: No such file or directory

stdoutここでは以前に印刷されたように見えますが、始めはstderr同じstderr文字数で「切り捨てられた」ことがわかりますstdout

の長さstdoutは6文字(foo fzキャリッジリターンを含む)なので、stderrls: ca)の最初の6文字を上書きしますstdout。だから実際には貼ったものではなく、stderr最初に印刷してからstdout印刷したように見えます。stderr

stderrしかし、もしそうなら、私にもっと意味があるでしょう。完全stdout部分的な上書きの代わりに削除して交換してください。

構文#4:

構文#3を修正する唯一の方法は、次に追加の演算子を追加することですstdout

$ ls file1 foo fz file2 >> redirect 2> redirect

または

$ ls file1 foo fz file2 2> redirect >> redirect

結果は構文#2と同じです。

ls: cannot access file1: No such file or directory
ls: cannot access file2: No such file or directory
foo
fz

この記事はこちら構文#3が間違っていることを説明します(おそらく構文#4も間違っているでしょう)。しかし、議論のために構文#3が間違っているのはなぜですか?一体何を言っているのでしょうか(あるいはいいえTell)シェルに構文#2以外の操作を実行させますか?

stderrまた、出力が常に以前に表示される理由はありますかstdout

ありがとうございます!

答え1

これは、同じファイルに同時に書き込む2つのプロセスを実行するのと同じです。これは悪い考えです。 2つの異なるオープンファイルハンドルが発生し、データが歪む可能性があります(上記の#3を参照)。構文#2を使用するのは正しいです。一つファイルハンドルを使用して、stderrとstdoutを同じ場所にポイントします。

stderrが常に最初に印刷されるという規則はありません。私は、lsこれがls特定のファイルが存在しないことを実際に宣言する前に、ディレクトリ内のすべてのエントリをチェックする必要があるためだと思います。したがって、ディレクトリテーブルを介してN回パスするのではなく、単一パスを作成し、指定されたすべてのコマンドライン引数を確認し、エラーを報告し、見つかったファイルを印刷します。他のコマンドはstdoutの後にstderrで印刷することも、それらの間を交互に印刷することもできます。

答え2

stdout通常、バッファリング(後で記録するためにメモリに保存)stderrまたは絶対に(何かが書き込まれる前にプログラムがクラッシュしてもエラーメッセージを表示したい)ワイルドカード応答に追加します。だからstderr通常より早く来ます。

答え3

これは開発者やカーネルの専門家ではありません。したがって、コードについて言及することはできませんが、構文#3では、2つの異なるパイプを使用して同じファイルにstdoutパイプをリンクしています。stderrしたがって、両方の出力を送信する共通ファイルには、2つの異なるパイプでリソース競合の問題がある可能性があります。オペレーティングシステムの非リアルタイム特性を考慮すると、両方のパイプラインが同時に同じファイルに情報を入力できます。これは不足している文字を説明する可能性があります。

構文#2では、ファイルにパイプが入り、シェルが競合状態に応じてパイプを管理するのとstderr同じパイプにリダイレクトします。stdout

これは私が経験した推測であり、単に推測です。これを確認できるものはありません。

関連情報