如何编写 bash 脚本tail -f filename.log
以在文件中遇到与以下行之一匹配的行时退出
Abaqus JOB filename COMPLETED
Abaqus/Analysis exited with errors
我知道可以使用Ctrl+C退出tail -f
,但正在寻找自动化的方法来做到这一点。
如有任何帮助,我们将不胜感激。
答案1
tail -f filename.log | sed '/Abaqus JOB filename COMPLETED/q'
至于“为什么有人需要这个”会吸引缺乏想象力的人:因为它可能滚动得太快,你可能会错过它。但您仍然想检查其进度。而且您仍然希望将其后一部分显示在屏幕上。
答案2
#!/bin/bash
p1="Abaqus/Analysis exited with errors"
p2="Abaqus JOB filename COMPLETED"
if tail /tmp/filename.log | grep -we "$p1" -we "$p2" > /dev/null 2>&1; then
echo "pattern found"
# ....do somenthing - what you need to do....
else
echo "pattern not found"
fi
无限循环:
while true; do
if tail /tmp/filename.log | grep -we "$p1" -we "$p2" > /dev/null 2>&1; then
echo "pattern found !"
# ....do something here....
break
fi
sleep 1
done
答案3
sh -c 'echo "$$"; exec tail -f filename.log' | (
IFS= read -r pid &&
sed '/^Abaqus JOB filename COMPLETED$/q
/^Abaqus\/Analysis exited with errors$/q' &&
kill -s PIPE "$pid"
)
如果我们只这样做tail -f file.log | sed ...q
,sed
就会q
在看到任何这些行时退出,但tail
只有在之后向管道写入任何内容时才会终止(被 SIGPIPE 杀死)。如果该日志文件永远不会更新,因为记录日志的进程已经死亡,那么这种情况永远不会发生。
因此,在这里,我们手动发送 SIGPIPE(而不是 SIGTERM,某些 shell 会导致打印不需要的诊断消息)。用于sh
将 的 pid tail
(由于 而重用了 的 pid sh
)exec
从一开始就传递到管道的右侧。
等价perl
的:
sh -c 'echo "$$"; exec tail -f filename.log' | perl -lne '
BEGIN {$pid = <> or die "No pid."}
print;
if ($_ eq "Abaqus JOB filename COMPLETED" ||
$_ eq "Abaqus/Analysis exited with errors") {
kill "PIPE", $pid;
last;
}'