パイプとリダイレクトについて

パイプとリダイレクトについて

このスクリプトを説明してください(ソース: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

現在、私はそれがどのように機能するかを想像しています。

  1. fd / 3出力をstdoutに接続するスクリプト
  2. パイプはstdoutをlsstdinに接続しますgrep(両方のプロセスはfd / 3を継承します)。
  3. lsstderrをstdoutにリダイレクトする
  4. stdoutがlsfd / 3に変更されます(したがって、プロセスはもはや出力を持たgrepず、エラーのみが発生します)。ls
  5. fd / 3が閉じました。ls

これが正しいリダイレクト順序ですか?

lsifでエラー出力が表示されず、fd / 3でリダイレクトされたstdoutを閉じる理由がわかりません。

grepfd/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として返すのに十分な長さを維持することです。lsfd / 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に渡して閉じないようにしてください。」。

おすすめ記事