如何同时打印日志文件内容并将其通过管道传输?
如何同时打印日志文件内容并将其通过管道传输?
我懂你的需求啦——既要实时盯着日志文件,把所有滚动的日志内容都输出到屏幕上,又要在捕捉到特定消息时自动停止监控对吧?之前你尝试用tee的方法确实会碰到命令一直卡着不退出的问题,原因其实很清楚:当grep -q找到匹配的消息后会立刻退出,但后台跑的tail -f还在一个劲儿输出内容给tee,tee会一直等着新输入,整个管道就停不下来了。
给你两个好用的解决办法:
方法一:用awk一站式搞定打印与匹配退出
awk可以同时完成“打印每一行日志”和“检测目标消息并退出”的工作,甚至还能顺手清理后台的tail进程,让整个命令彻底终止:
(tail -f -n 0 test.log &) | awk '{print} /SPEFICIC LOG MESSAGE/{exit}'
这个命令里,awk会先把每一行日志输出到屏幕,一旦匹配到SPEFICIC LOG MESSAGE就立刻退出。要是担心后台的tail进程残留,可以稍微升级一下,让awk退出前杀掉对应的tail进程:
(tail -f -n 0 test.log &) | awk '{print} /SPEFICIC LOG MESSAGE/{system("pkill -P " PROCINFO["ppid"] " tail"); exit}'
方法二:用进程组统一管理所有相关进程
另一种思路是把tail、tee和grep放到同一个进程组里,这样当grep退出时,整个进程组里的进程都会被终止,不会有残留:
sh -c 'tail -f -n 0 test.log | tee /dev/fd/2 | grep -q "SPEFICIC LOG MESSAGE"'
或者用更简洁的进程组控制语法:
(set -m; tail -f -n 0 test.log | tee /dev/fd/2 | grep -q "SPEFICIC LOG MESSAGE")
这样一来,grep找到目标退出后,tail和tee也会跟着停止,命令就能正常结束了。
补充:为啥之前的命令失效?
你之前写的(tail -f -n 0 test.log &) | tee /dev/fd/2 | grep -q 'SPEFICIC LOG MESSAGE'里,tail是在独立的子shell后台运行的,不属于主管道的进程组。所以grep退出后,tee还在等tail的输入,tail又会一直跑下去,导致整个命令卡着不结束。
备注:内容来源于stack exchange,提问作者not2savvy
相关产品推荐
相关产品推荐

