私はLinuxに初めてアクセスし、リダイレクトがどのように機能するかを理解しようとしています。
同じファイルにリダイレクトするためのさまざまな構文をテストしましたが、すべて同じ結果を生成するわけではありませんstdout
。stderr
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
キャリッジリターンを含む)なので、stderr
(ls: 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
これは私が経験した推測であり、単に推測です。これを確認できるものはありません。