私はショートシェルスクリプティングビデオコースを受講しており、提供された例の1つは次のとおりです。
if [[ ! $1 ]]; then
echo "Need line length argument" >&2
exit 1
fi
コース資料には、「これは標準エラーでエラーを印刷します」と記載されています。しかし、それは私の限られた理解には合いません。デフォルトのファイル記述子(指定されていない場合)は「1」です(したがって、この場合はstdout、つまり次のようになります)。上記1>&2
)。これはstdoutをstderrにリダイレクト/マージするようです。
リダイレクトの一部として「&」がどのように機能するかについての情報がありませんか?
答え1
それはただ誤解でした。 「これは、エラーを標準エラーとして印刷することです。」は、「標準エラーは出力が終わる場所です」を意味します。そうですね。 「stdoutをstderrにリダイレクト/マージ」です。しかし、これは矛盾ではありません。
コマンドはこの変更を認識しません。このコマンドはstdout
(例:fd 1)として印刷されます。ただし、コマンドを実行する前にシェルがstdout
作成されますstderr
。
$ strace -f bash -c '/bin/echo foo >&2'
[...]
dup2(1, 2) = 2
fcntl(1, F_GETFD) = 0
execve("/bin/echo", ["/bin/echo", "foo"], 0x55ffb063e5d0 /* 103 vars */) = 0
[...]
man 2 dup
int dup2(int oldfd, int newfd);
dup()システムコールは、最も低い番号の未使用のファイル記述子を新しい記述子として使用して、ファイル記述子oldfdのコピーを作成します。
正常に戻ったら、古いファイル記述子と新しいファイル記述子を入れ替えて使用できます。これらは同じオープンファイル記述(open(2)を参照)を参照するため、ファイルオフセットとファイルステータスフラグを共有します。たとえば、ファイルディスクリプタの1つでファイルオフセットを変更するためにlseek(2)を使用すると、もう1つはファイルディスクリプタのオフセットも変更されます。
両方のファイル記述子はファイル記述子フラグ(close-on-execフラグ)を共有しません。重複した記述子のclose-on-execフラグ(FD_CLOEXEC; fcntl(2)を参照)がオフになります。
答え2
また@HaukeLagingの返信、あなたは正しいです>&2
。これはの構文砂糖です1>&2
。&
ポインタまたは間接参照として解釈する必要があります。1>&2
デフォルトでは、コマンドは「このコマンド(または、{}
使用する場合はコマンドグループ)の場合、ファイル記述子1が単語()
を処理する前にファイル記述子2が指す場所を指します」を意味します。しかし、これはシェル構文であり、コマンドのパラメーターではありません。