'grep -q'不能以'tail -f'

我试图实现一个脚本,等待日志文件中的特定消息。 一旦消息被logging,然后我想继续脚本。

以下是我正在尝试使用tail -fgrep -q

 # tail -f logfile | grep -q 'Message to continue' 

grep永远不会退出,因此即使在文件中logging了“继续留言”,它也将永远等待。

当我运行这个没有-f似乎工作正常。

Solutions Collecting From Web of "'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 

经过一番实验,我认为问题就在于bash等待所有流程中的流程以某种形式或形式退出。

用360多行C源代码(各种程序连接好几遍)的简单文件'qqq',并用'grep -q return',我观察到:

  1. tail -n 300 qqq | grep -q return tail -n 300 qqq | grep -q return几乎立即退出。
  2. tail -n 300 -f qqq | grep -q return tail -n 300 -f qqq | grep -q return不退出。
  3. tail -n 300 -f qqq | strace -o grep.strace -q return tail -n 300 -f qqq | strace -o grep.strace -q return不会退出,直到中断。 grep.strace文件结束于:

     read(0, "#else\n#define _XOPEN_SOURCE 500\n"..., 32768) = 10152 close(1) = 0 exit_group(0) = ? 

    这是一个导致我认为grep已经退出中断杀死tail之前; 如果它在等待什么,就会有一个迹象表明它收到了一个信号。

  4. 一个简单的程序,模拟shell做什么,但没有等待,表明事情终止。

     #define _XOPEN_SOURCE 600 #include <stdlib.h> #include <unistd.h> #include <stdarg.h> #include <errno.h> #include <string.h> #include <stdio.h> static void err_error(const char *fmt, ...) { int errnum = errno; va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); if (errnum != 0) fprintf(stderr, "%d: %s\n", errnum, strerror(errnum)); exit(1); } int main(void) { int p[2]; if (pipe(p) != 0) err_error("Failed to create pipe\n"); pid_t pid; if ((pid = fork()) < 0) err_error("Failed to fork\n"); else if (pid == 0) { char *tail[] = { "tail", "-f", "-n", "300", "qqq", 0 }; dup2(p[1], 1); close(p[0]); close(p[1]); execvp(tail[0], tail); err_error("Failed to exec tail command"); } else { char *grep[] = { "grep", "-q", "return", 0 }; dup2(p[0], 0); close(p[0]); close(p[1]); execvp(grep[0], grep); err_error("Failed to exec grep command"); } err_error("This can't happen!\n"); return -1; } 

    使用固定大小的文件, tail -f不会退出 – 所以shell( bash )似乎在四处闲逛。

  5. tail -n 300 -f qqq | grep -q return tail -n 300 -f qqq | grep -q return挂起,但是当我用另一个终端添加另外300行到文件qqq ,命令退出。 我认为这是因为grep已经退出,所以当tail将新数据写入管道时,它得到一个SIGPIPE并退出,因此bash认识到管道中的所有进程都已经死了。

我观察到kshbash都有相同的行为。 这表明这不是一个错误,而是一些预期的行为。 在x86_64计算机上的Linux(RHEL 5)上进行测试。

 tail -f logfile | grep --max-count=1 -q 'Message to continue' 

无可否认,它在下一行被读取时退出,而不是立即在匹配的一行上。

我以为我会把这个作为答案,因为它解释了为什么该命令后第二次写入文件退出:

 touch xxx tail -f xxx | grep -q 'Stop' ps -ef |grep 'grep -q' # the grep process is there echo "Stop" >> xxx ps -ef|grep 'grep -q' # the grep process actually DID exit printf "\n" >> xxx # the tail process exits, probably because it receives a signal when it # tries to write to a closed pipe 

这是因为使用-f (follow)选项的tail不会退出,并继续向grep提供输出。 在日志文件中等待线可能会更容易与Perl / python。

使用Python子流程模块启动tail -f 。 在循环中从tail读取输出,直到看到所需的行,然后退出Python脚本。 把这个解决方案放在你的shell脚本中。

Python脚本将阻止shell脚本,直到看到所需的行。

我正在为自己的项目寻找答案。 尝试测试在VMware ESXi虚拟机上通过的GPU是否处于活动状态。 同一个问题的多种变化无处不在。 这个是最近的。 我想出了一个办法来愚弄它,如果你能在日志中重复你有趣的一行,那么:

tail -n 1 -f /var/log/vmkernel.log | grep -m 1 IOMMUIntel >> / var / log / vmkernel.log

这个日志是一次一行的,grep检查每一行的第一次出现,并把它附加到日志中,然后马上马上退出。

如果你喜欢VMware通过黑客入侵,请阅读更多: http ://hackaday.io/project/1071-the-hydra-multiheaded-virtual-computer