我想观看文件直到出现一些文本
我找到了这个答案:`tail -f` 直到看到文本
但是当我在 ubuntu 上尝试时,它不会退出:
$ echo one > test.txt
$ echo two >> test.txt
$ echo three >> test.txt
$ echo four >> test.txt
$ cat test.txt | sed '/w/ q'
one
two
$
按预期工作。但是当我尝试跟踪文件时
$ tail -f test.txt | sed '/w/ q'
one
two
它永远不会存在。即使管道破裂,尾巴也不会停止。
有人知道退出tail
时如何退出吗?sed
答案1
这与以下内容相同:
在:
cmd1 | cmd2
cmd1
即使您的 shellcmd2
已经终止,它也会一直等到终止。并非所有贝壳都是这样。例如,有些像 Bourne 或 Korn shell 就没有。
当cmd2
死亡时,标准输出上的管道cmd1
变成破碎的,但这不会cmd1
立即终止。
cmd1
将在下次尝试写入该管道时终止。然后它将收到一个 SIGPIPE,其默认操作是终止该进程。
使用cmd1
==tail -f file
和cmd2
== sed /w/q
,tail -f
将读取文件的最后 10 行并将它们写入 stdout(管道),通常是在一个块中,除非这些行真的很大并且坐在那里等待更多文本被附加到file
.
sed
,它同时运行,将等待其标准输入上的输入,读取它,逐行处理它,如果有一行包含w
.
一旦它发现该行(或者可能在某些实现中存在单行延迟sed
),它就会退出,但那时,它tail
已经将所有需要写入的内容写入管道,因此它不会收到 SIGPIPE,除非稍后会在文件中添加一些附加文本(此时它将执行 fatal 操作write()
)。
如果您想在终止cmd1
后立即终止cmd2
,则需要在 cmd2
终止后立即终止它。就像:
sh -c 'echo "$$"; exec tail -f test.txt' | {
IFS= read pid
sed /w/q
kill -s PIPE "$pid"
}
或者与bash
:
{ sed /w/q; kill -s PIPE "$!"; } < <(exec tail -f text.txt)
2020 编辑
正如 @user414777 所指出的,自版本 8.28 以来,在跟随模式下的 GNU 实现tail
现在不仅会轮询其监视的文件中的新数据,还会检查其 stdout 是否变成损坏的管道并立即退出(或在一秒内,如果inotify未使用),使得上述解决方法变得不必要。
但请注意,只有 GNUtail
进行这种处理,而不是任何其他实现tail
(据我所知),也不是任何其他实用程序(甚至是 GNU 实现)。
所以,同时:
tail -f file | head -n1
一行后将退出,
tail -f file | tr '[:lower:]' '[:upper:]' | head -n1
例如,不一定tr
会监视它的标准输出是否变成损坏的管道,因此只有在它出现时才会死亡写管道像往常一样破裂后会有一些东西(只有在那时 GNUtail -f
才会退出)。