为什么不是`tail -f ... | grep -q ...` 在找到匹配项时退出?

mac*_*ost 5 linux grep tail

我正在做一个非常标准的tail+ grep

tail -f some_log_file.txt | grep -q known-string
Run Code Online (Sandbox Code Playgroud)

如果我运行没有以下命令的命令-q

tail -f some_log_file.txt | grep known-string
Run Code Online (Sandbox Code Playgroud)

我看到输出:

[Tue Feb 12 11:32:45 2019] known-string.
Run Code Online (Sandbox Code Playgroud)

所以我知道grep是匹配的。但是,当我添加-qgrep 命令并没有退出时,它只是挂在那里等待更多输出......即使手册页说它会“如果找到任何匹配项,它将立即以零状态退出”:

   -q, --quiet, --silent
          Quiet;  do  not  write  anything  to  standard   output.    Exit
          immediately  with  zero status if any match is found, even if an
          error was detected.  Also see the -s or --no-messages option.
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么-q不导致我的 grep 退出?我试图将 a 链接&& beep到最后,以便在grep找到匹配项时发出哔哔声,但除非我可以让它退出,否则将无法正常工作。

har*_*ymc 5

从 StackOverflow 帖子 'grep -q' not exiting with 'tail -f'

tail -f将读取文件并显示稍后添加的行,它不会终止(除非发送类似信号SIGTERM)。grep不是这里的阻塞部分,tail -f是。grep将从管道中读取直到它关闭,但它永远不会因为tail -f不退出并保持管道打开。


您的问题的解决方案可能是(未经测试并且很可能表现不佳):

tail -f logfile | while read line; do
  echo $line | grep -q 'find me to quit' && break;
done
Run Code Online (Sandbox Code Playgroud)

您将在链接的帖子中找到更多信息和解决方案。


Kam*_*ski 5

grep尽管tail一直在运行,但确实退出并且管道消失了。此错误报告日志以与您的用例非常相似的用例开始:

我想使用tailgrep跟踪文件,直到出现特定模式。但tail完成后不退出grep

$ echo xxx > /tmp/blabla
$ tail -f /tmp/blabla |grep -m1 --line-buffered "xxx"
xxx
Run Code Online (Sandbox Code Playgroud)

现在tail仍然尝试读取并仅在我再次写入时退出/tmp/blabla

这是应该的样子吗?

那里的解释:

tail确实在 SIGPIPE 上退出,但是它只会在 上获得信号write(),因此您需要在文件中获取更多数据才能tail退出。

据我所知,这种确切的机制非常普遍。许多工具尝试向损坏的管道写入内容退出,这不是错误。

然后这个愿望来了:

尽管如此,这是一个公平的观点tail,因为它可以永远存在,应该采取特殊措施来响应管道的另一端消失。

最后:

实现于:https :
//git.sv.gnu.org/cgit/coreutils.git/commit/?id=v8.27-42-gce0415f

事实上,当我尝试tail从 GNU coreutils 8.28重现您的问题时,我不能。该工具立即退出。