'grep -q'不使用“tail -f”退出
我正在尝试实现一个等待日志文件中特定消息的脚本。记录消息后,我想继续执行脚本。
这是我正在尝试使用 tail -f
和 grep -q
进行的操作:
# tail -f logfile | grep -q 'Message to continue'
grep
永远不会退出,因此它会永远等待,即使“消息发送到continue' 已记录在文件中。
当我在没有 -f
的情况下运行它时,它似乎工作正常。
I am trying to implement a script that wait for a specific message in a log file. Once the message is logged then I want to continue the script.
Here's what I am trying out with tail -f
and grep -q
:
# tail -f logfile | grep -q 'Message to continue'
The grep
never quit and so it waits forever even if 'Message to continue' is logged in the file.
When I run this without -f
it seems to work fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
tail -f
将读取文件并显示稍后添加的行,它不会终止(除非发送像SIGTERM
这样的信号)。grep
不是这里的阻塞部分,tail -f
是。 grep 将从管道中读取数据,直到它关闭,但它永远不会关闭,因为tail -f 不会退出并保持管道打开。
您的问题的解决方案可能是(未经测试并且很可能表现不佳):
tail -f
will read a file and display lines later added, it will not terminate (unless a signal likeSIGTERM
is sent).grep
is not the blocking part here,tail -f
is.grep
will read from the pipe until it is closed, but it never is becausetail -f
does not quit and keep the pipe open.A solution to your problem would probably be (not tested and very likely to perform badly):
经过一些实验,我认为问题出在 bash 等待管道中的所有进程以某种形式退出的方式。
使用大约 360 行 C 源代码的纯文件“qqq”(各种程序多次连接),并使用“grep -q return”,然后我观察到:
tail -n 300 qqq | grep -q return 几乎立即退出。
尾-n 300 -f qqq | grep -q return 不退出。
<代码>tail -n 300 -f qqq | strace -o grep.strace -q return 在中断之前不会退出。
grep.strace
文件结尾为:这让我认为
grep
在中断杀死tail
之前就退出了;如果它正在等待某事,就会显示它收到了信号。一个简单的程序,模拟 shell 的功能,但无需等待,表明事情终止。
<前><代码>#define _XOPEN_SOURCE 600;;;;;;
#include
#include
#include
#include
#include
#include
静态无效 err_error(const char *fmt, ...)
{
int errnum = errno;
va_list 参数;
va_start(参数,fmt);
vfprintf(stderr, fmt, args);
va_end(参数);
if (errnum!= 0)
fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
退出(1);
}
int 主函数(无效)
{
int p[2];
如果(管道(p)!= 0)
err_error("创建管道失败\n");
pid_t 进程号;
if ((pid = fork()) < 0)
err_error("分叉失败\n");
否则如果(pid == 0)
{
char *tail[] = { "tail", "-f", "-n", "300", "qqq", 0 };
dup2(p[1], 1);
关闭(p[0]);
关闭(p[1]);
execvp(尾[0], 尾);
err_error("执行尾部命令失败");
}
别的
{
char *grep[] = { "grep", "-q", "return", 0 };
dup2(p[0], 0);
关闭(p[0]);
关闭(p[1]);
execvp(grep[0], grep);
err_error("执行 grep 命令失败");
}
err_error("这不可能发生!\n");
返回-1;
}
对于固定大小的文件,
tail -f
不会退出 - 因此 shell (bash
) 似乎会挂起。尾-n 300 -f qqq | grep -q return
一直挂着,但是当我使用另一个终端向文件qqq
添加另外 300 行时,该命令退出了。我将这种情况解释为发生的原因是grep
已退出,因此当tail
将新数据写入管道时,它收到 SIGPIPE 并退出,并且bash
> 因此认识到管道中的所有进程都已死亡。我在
ksh
和bash
中观察到相同的行为。这表明这不是一个错误,而是一些预期的行为。在 x86_64 计算机上的 Linux (RHEL 5) 上进行测试。After some experimentation, I believe the problem is in the way that
bash
waits for all the processes in a pipeline to quit, in some shape or form.With a plain file 'qqq' of some 360 lines of C source (a variety of program concatenated several times over), and using 'grep -q return', then I observe:
tail -n 300 qqq | grep -q return
does exit almost at once.tail -n 300 -f qqq | grep -q return
does not exit.tail -n 300 -f qqq | strace -o grep.strace -q return
does not exit until interrupted. Thegrep.strace
file ends with:This is one leads me to think that
grep
has exited before the interrupt killstail
; if it was waiting for something, there would be an indication that it received a signal.A simple program that simulates what the shell does, but without the waiting, indicates that things terminate.
With a fixed size file,
tail -f
isn't going to exit - so the shell (bash
) seems to hang around.tail -n 300 -f qqq | grep -q return
hung around, but when I used another terminal to add another 300 lines to the fileqqq
, the command exited. I interpret this as happening becausegrep
had exited, so whentail
wrote the new data to the pipe, it got a SIGPIPE and exited, andbash
therefore recognized that all the processes in the pipeline were dead.I observed the same behaviour with both
ksh
andbash
. This suggests it is not a bug but some expected behaviour. Testing on Linux (RHEL 5) on an x86_64 machine.诚然,它在读取下一行时退出,而不是立即在匹配的行上退出。
Admittedly, it exits when the next line is read, not immediately on the matched one.
我想我应该将此作为答案发布,因为它解释了为什么命令在第二次写入文件后退出:
I thought I'd post this as an answer since it explains why the command exits after a second write to the file:
这是因为带有
-f
(跟随)选项的tail
不会退出,而是继续向grep
提供输出。使用 perl/python 等待日志文件中的行可能会更容易。使用 Python 子进程模块启动
tail -f
。循环读取tail
的输出,直到看到所需的行,然后退出 Python 脚本。将此解决方案放入您的 shell 脚本中。Python 脚本将阻止 shell 脚本,直到看到所需的行。
That's because
tail
with the-f
(follow) option doesn't quit, and continues to provide output togrep
. Waiting for lines in a log file would probably be easier with perl/python.Launch
tail -f
with the Python subprocess module. Read output fromtail
in a loop until you see the lines you want then exit the Python script. Put this solution inside your shell script.The Python script will block the shell script until the desired lines are seen.
我正在为我自己的项目寻找这个问题的答案。尝试测试传递的 GPU 何时在 VMware ESXi 虚拟机上变为活动状态。同一问题的多种变体随处可见。这是最近的。我想出了一种方法来欺骗它,如果您可以接受日志中重复的有趣行,那么:
tail -n 1 -f /var/log/vmkernel.log | grep -m 1 IOMMUIntel>>/var/log/
vmkernel.log
这会跟踪日志,一次一行,grep 检查每一行是否第一次出现,并将其附加到日志中,然后 tail 立即退出。
如果您喜欢 VMware passthrough hacking,请在此处阅读更多内容:
http://hackaday.io/project/1071-the-Hydra-multiheaded -虚拟计算机
I was searching for the answer to this for my own project. Trying to test when exactly the passed through GPU becomes active on a VMware ESXi VM. Multiple variations of the same question are everywhere. This one is pretty recent. I figured out a way to fool it, and if you can live with your interesting line repeated in the log then:
tail -n 1 -f /var/log/vmkernel.log | grep -m 1 IOMMUIntel >>/var/log/
vmkernel.log
This tails the log, one line at a time, grep checks each line for first occurrence, and appends it to the log then tail quits immediately.
If you like VMware passthough hacking, read more here:
http://hackaday.io/project/1071-the-hydra-multiheaded-virtual-computer