如果文件中遇到与特定行匹配的行,则退出 Bash 脚本 (tail -f filename.log)

如果文件中遇到与特定行匹配的行,则退出 Bash 脚本 (tail -f filename.log)

如何编写 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 ...qsed就会q在看到任何这些行时退出,但tail只有在之后向管道写入任何内容时才会终止(被 SIGPIPE 杀死)。如果该日志文件永远不会更新,因为记录日志的进程已经死亡,那么这种情况永远不会发生。

因此,在这里,我们手动发送 SIGPIPE(而不是 SIGTERM,某些 shell 会导致打印不需要的诊断消息)。用于sh将 的 pid tail(由于 而重用了 的 pid shexec从一开始就传递到管道的右侧。

等价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;
  }'

相关内容