stderrのみパイプにリダイレクト

stderrのみパイプにリダイレクト

このコードスニペットのソースは次のとおりです。高度なバッシュスクリプトガイド

# Redirecting only stderr to a pipe.

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.

# Thanks, S.C.

コメントでは、コードが「grep」に対してfd 3のみをオフにすることを説明します。しかし、fd 3を2回閉じます。なぜ私たちはこれをすべきですか? 「grep」に対してfd 3を一度だけ閉じるのは間違っていますか?

ls -l 2>&1 >&3 | grep bad 3>&-    

ベストアンサー1

lsfd 3で何も開く必要はないのでgrep(そのfdを使用しない)、閉じることをお勧めします(不要なリソースを解放します)。 fd 3を使用してlsstdoutを元の出力に復元します(実行前ls)。

パイプラインでは、すべてのコマンドが独自のプロセスで同時に実行されることに注意してください。リダイレクトはそれぞれに個別に適用されるため、1つのfd 3を閉じると、もう1つのfd 3を閉じることはできません。

この場合、閉じないとファイルディスクリプタの数の制限に早く到達できることを除いて、閉じたり閉じたりしなくても実際に大きな違いはありません。

他の場合(たとえば、コマンド自体が別のプロセスを開始した場合など)、これはリソースを束ねて問題を引き起こす可能性があります。たとえば、stdoutがパイプの場合、バックグラウンドプロセスは最終的にfdを継承し、プロセスが返されるまでパイプリーダーでEOFを見ることができなくなります。

より良い書き方は次のとおりです。

{ ls -l 2>&1 >&3 3>&- | grep bad 3>&-; } 3>&1

このように、fd 3はそのコマンドグループ期間中に一時的にのみリダイレクトされます(そして後で復元または閉じます)。

違いを確認してください:

$ { ls -l /proc/self/fd 2>&1 >&3 3>&- | grep bad 3>&-; } 3>&1
total 0
lrwx------ 1 stephane stephane 64 Apr  2 09:29 0 -> /dev/pts/4
lrwx------ 1 stephane stephane 64 Apr  2 09:29 1 -> /dev/pts/4
l-wx------ 1 stephane stephane 64 Apr  2 09:29 2 -> pipe:[575886]
lr-x------ 1 stephane stephane 64 Apr  2 09:29 3 -> /proc/20918/fd/
$ { ls -l /proc/self/fd 2>&1 >&3  | grep bad 3>&-; } 3>&1
total 0
lrwx------ 1 stephane stephane 64 Apr  2 09:29 0 -> /dev/pts/4
lrwx------ 1 stephane stephane 64 Apr  2 09:29 1 -> /dev/pts/4
l-wx------ 1 stephane stephane 64 Apr  2 09:29 2 -> pipe:[575900]
lrwx------ 1 stephane stephane 64 Apr  2 09:29 3 -> /dev/pts/4
lr-x------ 1 stephane stephane 64 Apr  2 09:29 4 -> /proc/20926/fd/

2番目の呼び出しでは、lsfd 3も何らかの理由で端末に開きます(パイプを実行するとstdoutで開きます)。

ksh93では、を使用すると、execそのfdを閉じる必要はありません。 0、1、2以外のfdは、命令実行時に自動的に閉じられるからです。

$ ksh93 -c 'exec 3>&1; ls -l /dev/fd/'
total 0
lrwx------ 1 stephane stephane 64 Apr  2 09:34 0 -> /dev/pts/16
lrwx------ 1 stephane stephane 64 Apr  2 09:34 1 -> /dev/pts/16
lrwx------ 1 stephane stephane 64 Apr  2 09:34 2 -> /dev/pts/16
lr-x------ 1 stephane stephane 64 Apr  2 09:34 3 -> /proc/21105/fd
$ ksh93 -c 'exec 3>&1; ls -l /dev/fd/ 3>&3'
total 0
lrwx------ 1 stephane stephane 64 Apr  2 09:34 0 -> /dev/pts/16
lrwx------ 1 stephane stephane 64 Apr  2 09:34 1 -> /dev/pts/16
lrwx------ 1 stephane stephane 64 Apr  2 09:34 2 -> /dev/pts/16
lrwx------ 1 stephane stephane 64 Apr  2 09:34 3 -> /dev/pts/16
lr-x------ 1 stephane stephane 64 Apr  2 09:34 4 -> /proc/21108/fd

なぜそのような言葉が出てくるのかわかりません。(ただし「ls」ではない)上記はバグのようです(おそらく私;-)。

おすすめ記事