使用尾巴跟踪日志并立即执行命令?似乎只能通过开始一个新行来工作

using tail to follow a log and execute a command instantly? Only seems to work by starting a new line

我想找出一个命令,使我能够实时读取日志文件并在字符串匹配时执行命令?我正在使用 logkeys 并试图在我输入一个词时立即触发一个命令。这个脚本有效,但只有当我按下回车键(开始一个换行符)时它才会执行,而且我在网上找到的任何东西似乎也需要按下回车键才能工作。有什么办法可以解决这个问题吗?

#/bin/bash
echo Waiting...
string='test'
tail /path/to/logfile -n0 -f | while read line; do
        if [[ $line =~ $string ]]; then
                echo "hello"
        fi
done

我试过缓冲设置但没有用,所以我的结论是 read 在完成之前等待换行符。如果您改为 read -n1read 将恰好读取一个字符,这也不是我们想要的,因为那样 $line 将始终只是那个字符。

不幸的是,grep 似乎具有相同的行为(即使更改了缓冲选项),即使 grep -o:

$ tail logfile -f -n0 | grep -o test &
[1] 25524
$ echo -n test >> logfile
$ echo -n test >> logfile
$ echo test >> logfile
test
test
test

认为一般的解决方案是使用我们自己的"ring buffer grep"搜索工具,将每个字符读入环形缓冲区。

这是我的 perl 版本,希望对您有所帮助。 (另存为:ringgrep.pl

#!/usr/bin/perl -w

use strict;

if (!$ARGV[0]) {
    print "Usage: [=11=] needle\n";
    exit 1;
}
my $needle = $ARGV[0];
my $buffer_len = length($needle);
my @buffer = (0) x $buffer_len;
my $i = 0;
my $input;

while(sysread(STDIN, $input, 1)) {
    $buffer[$i] = $input;
    my $string = join("", @buffer);
    $string = (($i+1)%$buffer_len == 0 ? "" : substr($string, $i-$buffer_len+1)) . substr($string, 0, $i+1);
    # print "string is: $string\n";
    if ($string =~ /$needle/) {
        print "got test!\n";
        @buffer = (0) x $buffer_len;
        $i = 0
    } else {
        $i = (++$i) % $buffer_len
    }
}

用法:

$ chmod +x ringgrep.pl
$ tail logfile -n0 -f | ./ringgrep.pl "this is a test" &
[1] 25756
$ echo -n "test" >> logfile
$ echo -n "test" >> logfile
$ echo -n "test" >> logfile
$ echo -n "test" >> logfile
$ echo -n "this is a test" >> logfile
got test!
$ echo -n "this is a test" >> logfile
got test!
$ echo -n "this is a test" >> logfile
got test!
$ (echo -n t; echo -n h; echo -n i; echo -n s; echo -n ' '; echo -n i; echo -n s; echo -n ' '; echo -n a; echo -n ' '; echo -n t; echo -n e; echo -n s; echo -n t) >> logfile
got test!