我正在做一个非常标准的tail
+ grep
:
tail -f some_log_file.txt | grep -q known-string
如果我运行不带以下选项的命令-q
:
tail -f some_log_file.txt | grep known-string
我看到输出:
[Tue Feb 12 11:32:45 2019] known-string.
所以我知道 grep 匹配了。但是当我添加-q
grep 命令时,它并没有退出,而是挂在那里等待更多输出……尽管手册页说“如果找到任何匹配项,它将立即以零状态退出”:
-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.
有人能解释一下为什么-q
我的 grep 不会退出吗?我试图将 a 链接&& beep
到最后,这样grep
当找到匹配项时就会发出哔哔声,但除非我能让它退出,否则不会起作用。
答案1
来自 StackOverflow 帖子 ‘grep -q’ 不会以 ‘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
您将在链接的帖子中找到更多信息和解决方案。
答案2
grep
确实退出并且管道消失,尽管tail
继续运行。此错误报告日志从与您的非常相似的用例开始:
我想使用
tail
并grep
跟踪文件直到出现特定模式。但完成tail
后不会退出。grep
$ echo xxx > /tmp/blabla $ tail -f /tmp/blabla |grep -m1 --line-buffered "xxx" xxx
现在
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 重现您的问题时,我无法重现。该工具立即退出。