使用尾巴跟踪日志并立即执行命令?似乎只能通过开始一个新行来工作
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 -n1
,read
将恰好读取一个字符,这也不是我们想要的,因为那样 $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!
我想找出一个命令,使我能够实时读取日志文件并在字符串匹配时执行命令?我正在使用 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 -n1
,read
将恰好读取一个字符,这也不是我们想要的,因为那样 $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!