シェルスクリプトの出力をリダイレクトしたときに、やや奇妙な動作を見つけました。スクリプト自体がいくつかの出力を/dev/stdoutまたは/dev/stderrにリダイレクトしました。
シェルスクリプト
$ cat test.sh
#!/bin/bash -x
echo stdout
echo stderr >&2
echo '/dev/stdout' > /dev/stdout
echo '/dev/stderr' > /dev/stderr
基準:リダイレクトなし
$ ./test.sh
+ echo stdout
stdout
+ echo stderr
stderr
+ echo /dev/stdout
/dev/stdout
+ echo /dev/stderr
/dev/stderr
リダイレクトを実行しないと、すべてが期待どおりに表示されます。
標準出力リダイレクト
$ ./test.sh > out
+ echo stdout
+ echo stderr
stderr
+ echo /dev/stdout
+ echo /dev/stderr
/dev/stderr
$ cat out
/dev/stdout
stdoutをリダイレクトすると、「/dev/stdout」行は期待どおりにリダイレクトされますが、「stdout」行はどこにも表示されません。
ストリームを別々のファイルにリダイレクトする
$ ./test.sh > out 2> err
$ cat out
/dev/stdout
$ cat err
/dev/stderr
「stderr」だけでなく、「bash -x」の行も消えました。
ストリームを同じファイルにリダイレクトする
$ ./test.sh > out 2>&1
$ cat out
/dev/stderr
最後のケースでは、前の例のすべての内容が失われ、以前にファイルに正常にリダイレクトされた "/dev/stdout"も失われます。
たとえば、シェルスクリプトでexec行を使用してリダイレクトすると、exec 1>out; exec 2>&1;
コマンドラインからリダイレクトするのと同じ動作が発生します。
質問:行が不足しているのはなぜですか?これは、スクリプトのすべての行(コマンドラインリダイレクトを介して実行された暗黙的に実行された行を含む)で何が起こるのですか?好ましくは、後者の回答に関連するシステムコール(dup2?)について説明します。
答え1
ファイルにリダイレクトしているため
echo '/dev/stdout' > /dev/stdout
echo '/dev/stderr' > /dev/stderr
ファイルに追加せずに上書きします。リダイレクトしないと、stdout / stderrにのみ追加できるため、これはわかりません。
使用。 。 。交換
echo '/dev/stdout' >> /dev/stdout
echo '/dev/stderr' >> /dev/stderr
すべてが正常に戻った。