stdoutとstderrを同じファイルにリダイレクトするには、command 1>file.txt 2>&1
またはを使用できますcommand &>file.txt
。しかし、command 1>file.txt 2>file.txt
上記の2つのコマンドと動作が異なるのはなぜですか?
以下は確認コマンドです。
$ cat redirect.sh
#!/bin/bash
{ echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file.txt 2>&1
{ echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file1.txt 2>file1.txt
{ echo -e "error" 1>&2 && echo -e "output\noutput"; } 1>file2.txt 2>file2.txt
{ echo -e "output" && echo -e "error\nerror" 1>&2; } 1>file3.txt 2>file3.txt
{ echo -e "error\nerror" 1>&2 && echo -e "output"; } 1>file4.txt 2>file4.txt
$ ./redirect.sh
$ echo "---file.txt---"; cat file.txt;\
echo "---file1.txt---"; cat file1.txt; \
echo "---file2.txt---"; cat file2.txt; \
echo "---file3.txt---"; cat file3.txt; \
echo "---file4.txt----"; cat file4.txt;
---file.txt---
output
output
error
---file1.txt---
error
output
---file2.txt---
output
output
---file3.txt---
error
error
---file4.txt----
output
rror
結果を見ると、実行時に2番目のエコー文字列が最初のエコー文字列を上書きしているように見えますが、command 1>file.txt 2>file.txt
なぜこれが起こるのかわかりません。 (参考にできるところはありますか?)
ベストアンサー1
次の2つを知る必要があります。
- オープンファイル記述子プロセスのアプリケーションモード側は、以下の内部カーネルオブジェクトを参照することが知られています。ファイル説明、ファイルを開くインスタンスです。各ファイルには複数のファイル記述があり、複数のファイル記述子がファイル記述を共有します。
- これ現在のファイルの場所の属性ですファイル説明。したがって、複数のファイル記述子が単一のファイル記述にマップされている場合は、すべて同じ現在のファイル場所を共有し、これらのファイル記述子を使用してファイルの場所を変更すると、他のすべてのファイル記述子に影響します。
これらの変更は、
read()
/readv()
、write()
/writev()
などのシステムコールを呼び出すlseek()
プロセスによって実装されます。echo
もちろん、このコマンドはwrite()
/を呼び出します。writev()
だから何が起こるのか:
command 1>file.txt 2>&1
シェルはファイルを一度だけ開くので、1つのファイル記述のみが生成されます。シェルが作る両方標準出力および標準エラーファイル記述子は、この単一ファイル記述にマップされます。それ重複標準出力は標準エラーに切り替わります。したがって、両方のファイル記述子を介して書き込むと、共有内の現在のファイルの場所が移動されます。各書き込みは、以前に共通ファイル記述子に書き込んだ後に発生します。ご覧のとおり、コマンドの結果はecho
互いに上書きされません。command 1>file.txt 2>file.txt
作る二つこれは、2つの明示的なリダイレクトに応答してシェルが同じファイルを2回開くので、ファイルの説明です。標準出力および標準エラー・ファイル記述子は、2 つの異なるファイル記述にマップされ、同じファイルに再マップされます。両方のファイル記述は完全に独立した現在のファイル位置を持ち、各書き込みは同じファイル記述に対する直前の書き込みをすぐに実行します。見てわかるように、その結果、一方の側で書き込まれた内容は、書き込みを実行する順序に応じて、さまざまな方法で他方を介して書き込まれた内容を上書きできます。