SH/BASH - 扫描日志文件直到出现一些文本,然后退出。如何?

发布于 2024-08-28 01:54:24 字数 544 浏览 5 评论 0原文

编辑 - 4 月 7 日对问题进行了一些修改,以使其更加清晰。

当前的工作环境是OSX 10.4.11。

我想扫描日志文件中的某个短语。日志文件不能在脚本开始时清空。因此,脚本必须仅扫描日志的更改。

我当前的脚本:

#!/bin/sh
  tail -f log.txt | while read line 
do
  if echo $line | grep -q 'LOL CANDY'; then
    echo 'LOL MATCH FOUND'
    exit 0
  fi
done

它工作正常,因为它会在找到“LOL CANDY”后立即“LOL MATCH FOUND”,但它实际上不会退出脚本,直到“LOL CANDY”之后的日志中添加了一些其他内容。我需要它立即退出。尽管我不确定它是否具体相关,但存在“tail -f”永远保持打开状态的问题。有人可以给我一个不使用 tail -f 也能工作的例子吗?

如果你愿意,你可以给我一个 bash 脚本,因为 OSX 可以处理 sh、bash 和我认为的其他一些 shell。

Edit - Reworded the question a bit on April 7th to make it clearer.

Current working environment is OSX 10.4.11.

I want to scan a log file for a certain phrase. The log file can NOT be emptied at the start of the script. Thus, the script must scan only changes to the log.

My current script:

#!/bin/sh
  tail -f log.txt | while read line 
do
  if echo $line | grep -q 'LOL CANDY'; then
    echo 'LOL MATCH FOUND'
    exit 0
  fi
done

It works properly in the fact that it will 'LOL MATCH FOUND' immediately after finding 'LOL CANDY', but it will not actually quit the script until there is some other addition to the log AFTER the 'LOL CANDY'. I need it to immediately quit. And although I'm not sure it is specifically related, there is the problem of the "tail -f" staying open forever. Can someone please give me an example that will work without using tail -f?

If you want you can give me a bash script, as OSX can handle sh, bash, and some other shells I think.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不如归去 2024-09-04 01:54:24

第二次启动脚本时是否清除 log.txt?您可能会认为戒烟热线需要出现两次,而实际上只需要出现一次。因为您使用的是 -f,所以它只会列出启动脚本后添加的所有内容。

所以当你第一次跟踪它时,你得到了你想要的线路,然后你就退出了。您重新启动脚本,它将忽略第一个实例,因为它不会被输入到 tail 的 -f 参数中。然而,下一次发生应该退出。如果你查看日志,你会看到两条 LOL CANDY 行,因为你只是跟随尾巴,而不是查看日志中已有的内容。

如果您希望脚本在该行出现在日志中时终止,您可以将其添加到脚本的开头。

 #!/bin/sh
  if grep 'LOL CANDY' log.txt; then
   echo 'LOL MATCH FOUND'
   exit 0
  fi

  tail -f log.txt | while read line 
do
  if echo $line | grep -q 'LOL CANDY'; then
    echo 'LOL MATCH FOUND'
    exit 0
  fi
done

另外,如果您想摆脱 tail -f 您可以在无限 while 循环中执行我在第一个实例中列出的操作(语法可能是错误的,已经有一段时间了):

#!/bin/sh
while (1)
do
  if grep 'LOL CANDY' log.txt; then
   echo 'LOL MATCH FOUND'
   exit 0
  fi
done

当然,如果您的日志文件变得非常大,那么这将消耗大量资源并花费大量时间。

Are you clearing the log.txt when you launch your script the second time? You may be interpreting that it takes two appearances of your quit-line when actually it only takes one. Because you are using -f, it will only list everything added once you start up your script.

So the first time you tail it you get your wanted line and you quit. You re-launch the script, it will ignore the first instance because it is not going to be inputted into your -f argument to tail. However the next occurrance should quit. If you look into your log you will see two LOL CANDY lines because you are just following the tail and not looking at what is already in the log.

If you wanted your script to die anytime that line appears in the log, you could add this to the beginning of your script.

 #!/bin/sh
  if grep 'LOL CANDY' log.txt; then
   echo 'LOL MATCH FOUND'
   exit 0
  fi

  tail -f log.txt | while read line 
do
  if echo $line | grep -q 'LOL CANDY'; then
    echo 'LOL MATCH FOUND'
    exit 0
  fi
done

Also if you wanted to get rid of the tail -f you could do what I listed in the first instance in an infinite while loop (syntax might be wrong, been a while):

#!/bin/sh
while (1)
do
  if grep 'LOL CANDY' log.txt; then
   echo 'LOL MATCH FOUND'
   exit 0
  fi
done

Of course if your log file gets pretty large then this will eat up a lot of resources and take a lot of time.

探春 2024-09-04 01:54:24

也许这个脚本会帮助你:

#!/bin/bash

FILE=/tmp/mytest
PIPE=/tmp/myfifo

if [[ ! -p $PIPE ]];
then
        mkfifo $PIPE
fi

tail -n 0 -f $FILE >> $PIPE &
TAILPID=$!

while read line < $PIPE
do
        echo "Received: $line"
        if [ "x$(echo "$line" | grep -l -P "asdf")" != "x" ];
        then
                echo "MATCHES"
                kill -TERM $TAILPID
        fi
done;

Maybe this script will help you:

#!/bin/bash

FILE=/tmp/mytest
PIPE=/tmp/myfifo

if [[ ! -p $PIPE ]];
then
        mkfifo $PIPE
fi

tail -n 0 -f $FILE >> $PIPE &
TAILPID=$!

while read line < $PIPE
do
        echo "Received: $line"
        if [ "x$(echo "$line" | grep -l -P "asdf")" != "x" ];
        then
                echo "MATCHES"
                kill -TERM $TAILPID
        fi
done;
傲世九天 2024-09-04 01:54:24
tail -f log.txt | sed -n '/interesting/{
p
q
}'

基本上,读取行而不打印任何内容;当你看到一些有趣的东西时,打印该行并退出。

哦,我知道你不想要“tail -f”;这很奇怪,当它下次需要写入管道时应该退出。如果它不再写入管道,那可能是一个问题。

我想你可以这样做:

tail -f log.txt | sed -n '/interesting/{
p
q
}'
echo "EOF" >> log.txt

这给了它一些回声,所以它尝试并失败并终止。

tail -f log.txt | sed -n '/interesting/{
p
q
}'

Basically, read lines without printing anything; when you see something interesting, print the line and quit.

Oh, I see you want no 'tail -f'; that's odd, it should quit when it next needs to write to the pipe. If it never writes to the pipe again, that could be a problem.

I suppose you could do:

tail -f log.txt | sed -n '/interesting/{
p
q
}'
echo "EOF" >> log.txt

That gives it something to echo, so it tries and fails and terminates.

少女净妖师 2024-09-04 01:54:24

试试这个

(tail -f  file| awk '/interesting/{print;exit}')

try this

(tail -f  file| awk '/interesting/{print;exit}')
木槿暧夏七纪年 2024-09-04 01:54:24

我不太确定我是否理解你的问题。
不管怎样,我尝试了你的脚本,它在第一次运行时没有退出。那么,

pid=`ps -ef | grep "tail -f log.txt" | grep -v grep | awk '{print $2}'`
kill -2 $pid

exit 0 之前添加 : 以便 tail -f 退出怎么样?

I am not quite sure if I understand your question.
Anyway, I tried your script, it did not quit on first run. So, How about adding :

pid=`ps -ef | grep "tail -f log.txt" | grep -v grep | awk '{print $2}'`
kill -2 $pid

before exit 0 so that the tail -f exits?

尬尬 2024-09-04 01:54:24

我一直在寻找这个,并找出了以下工作(无论如何对于我的应用程序):

tail -n 1 -f /var/log/vmkernel.log | grep -m 1 IOMMUIntel >>/var/log/vmkernel.log

尾部日志,grep找到文本,grep将文本写回log,这会杀死 tail,然后我回到提示符。

具体来说,当虚拟机在 VMware ESXi 上启动时,它会测试直通显卡何时变为活动状态。

完整的项目位于此处

I was looking for this, and figured out the following works (for my application anyway):

tail -n 1 -f /var/log/vmkernel.log | grep -m 1 IOMMUIntel >>/var/log/vmkernel.log

Tails the log, grep finds the text, and grep writes the text back to the log, which kills the tail and I'm back to the prompt.

Specifically, it tests when a passed through video card becomes active when a VM boots on VMware ESXi.

The full project is here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文