Cav*_*vaz 3 bash pipe tail sh process-substitution
我正在编写一个屏障来阻止脚本的执行,直到记录某个关键字为止。该脚本非常简单:
tail -F -n0 logfile.log | while read LINE; do
[[ "$LINE" == *'STOP'* ]] && echo ${LINE} && break;
done
Run Code Online (Sandbox Code Playgroud)
或者
tail -F -n0 logfile.log | grep -m1 STOP
Run Code Online (Sandbox Code Playgroud)
问题是它不会在检测到关键字后立即退出,而是仅在写入下一行后才退出。IE:
printf "foo\n" >> logfile.log # keeps reading
printf "foo\n" >> logfile.log # keeps reading
printf "STOP\n" >> logfile.log # STOP printed
printf "foo\n" >> logfile.log # code exits at last
Run Code Online (Sandbox Code Playgroud)
不幸的是,我不能依赖这样一个事实:在“STOP”之后将记录另一行(至少不在对我的目的有用的间隔内)。
到目前为止找到的解决方法是tail另一个我确信会经常更新的文件,但是“干净”的解决方案是什么,以便代码在记录STOP后立即退出?
在bash中,执行以下形式的命令时
command1 | command2
Run Code Online (Sandbox Code Playgroud)
并死亡或终止,接收command2的管道 破裂。然而,这不会立即终止。/dev/stdoutcommand1command1
所以要实现你想要的就是使用进程替换而不是管道
awk '/STOP/{exit}1' < <(tail -f logfile)
Run Code Online (Sandbox Code Playgroud)
当您使用awk时,您可以更详细地查看行为:
$ touch logfile
$ tail -f logfile | awk '/STOP/{exit}1;END{print "end"}'
Run Code Online (Sandbox Code Playgroud)
该awk程序将检查是否看到“STOP”,如果没有则再次打印该行。如果看到“STOP”,它将打印“end”
当您在另一个终端中执行操作时
$ echo "a" >> logfile
$ echo "STOP" >> logfile
$ echo "b" >> logfile
Run Code Online (Sandbox Code Playgroud)
您会看到awk打印以下输出:
a # result of print
end # awk test STOP, exits and executes END statement
Run Code Online (Sandbox Code Playgroud)
此外,如果您仔细观察,您会发现awk此时已经终止。
ps在发送“STOP”之前:
13625 pts/39 SN 0:00 | \_ bash
32151 pts/39 SN+ 0:00 | \_ tail -f foo
32152 pts/39 SN+ 0:00 | \_ awk 1;/STOP/{exit}1;END{print "end"}
Run Code Online (Sandbox Code Playgroud)
ps发送“STOP”后:
13625 pts/39 SN 0:00 | \_ bash
32151 pts/39 SN+ 0:00 | \_ tail -f foo
Run Code Online (Sandbox Code Playgroud)
因此 awk 程序终止,但tail没有崩溃,因为它尚未意识到管道已损坏,因为它没有尝试写入。
当您在终端中使用管道执行以下操作时,您会看到退出状态tail:
$ echo "${PIPESTATUS[0]} ${PIPESTATUS[1]}"
$ 141 0
Run Code Online (Sandbox Code Playgroud)
其中声明awk很好地终止,但tail以退出代码 141 终止,这意味着SIGPIPE.
| 归档时间: |
|
| 查看次数: |
3441 次 |
| 最近记录: |