このスクリプトを説明してください(ソース:ABSG。章。 20):
exec 3>&1 # Save current "value" of stdout.
ls -l 2>&1 >&3 3>&- | grep bad 3>&- # Close fd 3 for 'grep' (but not 'ls').
# ^^^^ ^^^^
exec 3>&- # Now close it for the remainder of the script
現在、私はそれがどのように機能するかを想像しています。
- fd / 3出力をstdoutに接続するスクリプト
- パイプはstdoutを
ls
stdinに接続しますgrep
(両方のプロセスはfd / 3を継承します)。 ls
stderrをstdoutにリダイレクトする- stdoutが
ls
fd / 3に変更されます(したがって、プロセスはもはや出力を持たgrep
ず、エラーのみが発生します)。ls
- fd / 3が閉じました。
ls
これが正しいリダイレクト順序ですか?
ls
ifでエラー出力が表示されず、fd / 3でリダイレクトされたstdoutを閉じる理由がわかりません。
grep
fd/3 終了 process() の目的は何ですかgrep bad **3>&-**
?
ベストアンサー1
ファイル記述子をファイルを値として受け入れる(またはI / Oストリームと呼ぶ)変数と考え、表示される順序を評価される順序で考えると役立ちます。
上記の例では、次のことが発生します。
1)スクリプトは次のように始まります(継承されない限りデフォルトで)。
fd/0 = stdin # that's the keyboard
fd/1 = stdout # that's the screen
fd/2 = stderr # the screen again, but different stream
2)このexec
コマンドは新しい変数を宣言し、値を割り当てると解釈されます。
fd/3 = fd/1 # same as stdout
これで、2つのファイル記述子の値はstdoutです。つまり、どちらも画面に印刷するために使用できます。
3)ls
開いているすべてのファイル記述子を実行して継承する前に、次の設定が行われます。
ls.fd/1 = grep.fd/0 # pipe gets precedence, ls.fd/1 writes to grep.stdin
ls.fd/2 = ls.fd/1 # ls.fd/2 writes to grep.stdin
ls.fd/1 = ls.fd/3 # ls.fd/1 writes to stdout
ls.fd/3 = closed # fd/3 will not be inherited by `ls`
fd / 3の目的は、標準出力値をfd / 1として返すのに十分な長さを維持することです。ls
fd / 1に送信されたすべての内容はstdinではなくstdoutに送信されますgrep
。
順序が重要です。たとえば、ls -l >&3 2>&1 3>&-
ls.fd / 2を実行すると、標準入力ではなく標準出力に書き込まれますgrep
。
4) fd/3 forgrep
は閉じており、継承されません。とにかく使用されます。grep
エラーメッセージのみをフィルタリングできます。ls
ABSGに提供されている例は最も役に立たないかもしれません。「grep」に対してfd 3を閉じます(ただし「ls」ではありません)。」は多少誤解を招くおそれがありますので、次のように読むことができます。lsの場合は、設定を解除する前にls.fd/3の値をls.fd/1に渡して閉じないようにしてください。」。