grep --exclude オプションが指定されたパイプを常にスキップするわけではありません。

grep --exclude オプションが指定されたパイプを常にスキップするわけではありません。

私は他のファイルの中に3つの名前付きパイプ(FIFO、FIFO1、およびFIFO11)を含むディレクトリを持っています。私が次のようなことをしようとすると

grep mypattern *

このディレクトリでは、grepは名前付きパイプに永久にかかっているため、これを除外する必要があります。意外に、

grep --exclude='FIF*' mypattern *

問題は解決されませんでした。 grepはまだ永遠に中断されます。しかし、

grep -r --exclude='FIF*' mypattern .

する停止の問題を解決します(すべてのサブディレクトリを検索するための望ましくない副作用があるにもかかわらず)。

いくつかのテストを試してみると、grep --exclude ='FIF*' mypattern *FIFOなどが名前付きパイプではなく通常のファイルである場合、期待どおりに動作することがわかりました。

質問:

  1. 通常のファイルの場合、どちらの場合も名前付きパイプをスキップし、再帰的なgrep場合は名前付きパイプをスキップしますが、非再帰的な場合はスキップしないのはなぜですか?--excludes--excluded
  2. どのような場合でも、これらのファイルをスキップする除外形式を指定する他の方法はありますか?
  3. 私が望むことを達成するためのより良い方法はありますか? (編集:私は
    --devices=skipgrepでフラグを見つけたので、これはその部分への答えです...しかし、まだ質問の最初の2つの部分が気になります。)

ベストアンサー1

grepまだそうだ開いている正規表現でファイルをスキップするように指示しても、次のようになります。

$ ll
total 4.0K
p-w--w---- 1 user user 0 Feb  7 16:44 pip-fifo
--w--w---- 1 user user 4 Feb  7 16:44 pip-file
lrwxrwxrwx 1 user user 4 Feb  7 16:44 pip-link -> file

(注:これらのいずれにも読み取り権限がありません。)

$ strace -e openat grep foo --exclude='pip*' pip-file pip-link pip-fifo
openat(AT_FDCWD, "pip-file", O_RDONLY|O_NOCTTY) = -1 EACCES (Permission denied)
grep: pip-file: Permission denied
openat(AT_FDCWD, "pip-link", O_RDONLY|O_NOCTTY) = -1 ENOENT (No such file or directory)
grep: pip-link: No such file or directory
openat(AT_FDCWD, "pip-fifo", O_RDONLY|O_NOCTTY) = -1 EACCES (Permission denied)
grep: pip-fifo: Permission denied
+++ exited with 2 +++

読み取り権限を付与して除外すると、開いた後に読み込もうとしないようです。

$ strace -e openat grep foo --exclude='pip*' pip-file pip-link pip-fifo
openat(AT_FDCWD, "pip-file", O_RDONLY|O_NOCTTY) = 3
openat(AT_FDCWD, "pip-link", O_RDONLY|O_NOCTTY) = -1 ENOENT (No such file or directory)
grep: pip-link: No such file or directory
openat(AT_FDCWD, "pip-fifo", O_RDONLY|O_NOCTTY^Cstrace: Process 31058 detached
 <detached ...>

$ strace -e openat,read grep foo --exclude='pip*' pip-file
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000\25\0\0\0\0\0\0"..., 832) = 832
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\r\0\0\0\0\0\0"..., 832) = 832
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260`\0\0\0\0\0\0"..., 832) = 832
openat(AT_FDCWD, "pip-file", O_RDONLY|O_NOCTTY) = 3
+++ exited with 1 +++

$ strace -e openat,read grep foo --exclude='pipe*' pip-file
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000\25\0\0\0\0\0\0"..., 832) = 832
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\r\0\0\0\0\0\0"..., 832) = 832
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260`\0\0\0\0\0\0"..., 832) = 832
openat(AT_FDCWD, "pip-file", O_RDONLY|O_NOCTTY) = 3
read(3, "foo\n", 32768)                 = 4
foo
read(3, "", 32768)                      = 0
+++ exited with 0 +++

~からopenat呼び出しは使用されず、O_NONBLOCK開始部分自体が中断され、grepは読み取りから除外された部分に到達できません。

ソースコードを見てみると、プロセスは次のようになります。

  1. 再帰的でない場合は、次を呼び出します。grep_command_line_argすべてのファイルに。
  2. これは…grepfile標準入力でない場合。
  3. grepfile着信電話grepdesc 後ろにファイルを開きます。
  4. grepdesc調査するこのファイルを除外

繰り返すとき:

  1. grepdirent 除外ファイルの確認呼び出す前にgrepfile失敗はopenat発生しません。

おすすめ記事