我有一个服务器日志,当服务器启动时,它会将特定的文本行输出到其日志文件中。我想在服务器启动后执行命令,因此执行如下操作:
tail -f /path/to/serverLog | grep "server is up" ...(now, e.g., wget on server)?
做这个的最好方式是什么?
答案1
一个简单的方法是 awk。
tail -f /path/to/serverLog | awk '
/Printer is on fire!/ { system("shutdown -h now") }
/new USB high speed/ { system("echo \"New USB\" | mail admin") }'
是的,这两条都是来自内核日志的真实消息。使用 Perl 可能会更优雅一些,并且还可以取代 tail 的需要。如果使用 perl,它将看起来像这样:
open(my $fd, "<", "/path/to/serverLog") or die "Can't open log";
while(1) {
if(eof $fd) {
sleep 1;
$fd->clearerr;
next;
}
my $line = <$fd>;
chomp($line);
if($line =~ /Printer is on fire!/) {
system("shutdown -h now");
} elsif($line =~ /new USB high speed/) {
system("echo \"New USB\" | mail admin");
}
}
答案2
如果您只想寻找一种可能性并且希望主要留在 shell 中而不是使用awk
or perl
,您可以执行以下操作:
tail -F /path/to/serverLog |
grep --line-buffered 'server is up' |
while read ; do my_command ; done
my_command
...每次都会运行“服务器已启动" 出现在日志文件中。对于多种可能性,您可以删除grep
并case
在while
.
大写-F
告诉tail
我们要注意要轮换的日志文件;IE如果当前文件被重命名并且另一个同名文件取代了它,tail
将切换到新文件。
该--line-buffered
选项指示grep
在每行之后刷新其缓冲区;否则,my_command
可能无法及时到达(假设日志具有合理大小的行)。
答案3
奇怪的是,没有人提到具有multitail
开箱即用功能的实用程序。使用示例之一:
显示 ping 命令的输出,如果显示超时,则向当前登录的所有用户发送一条消息
multitail -ex timeout "echo timeout | wall" -l "ping 192.168.0.1"
也可以看看另一个例子使用情况multitail
。
答案4
巴什可以自己做这项工作
让我们看看它是多么简单和可读:
mylog() {
echo >>/path/to/myscriptLog "$@"
}
while read line;do
case "$line" in
*"Printer on fire"* )
mylog Halting immediately
shutdown -h now
;;
*DHCPREQUEST* )
[[ "$line" =~ DHCPREQUEST\ for\ ([^\ ]*)\ ]]
mylog Incomming or refresh for ${BASH_REMATCH[1]}
$HOME/SomethingWithNewClient ${BASH_REMATCH[1]}
;;
* )
mylog "untrapped entry: $line"
;;
esac
done < <(tail -f /path/to/logfile)
虽然您不使用 bash regex
,但这可能会非常快!
但巴什+sed是一个非常高效且有趣的串联
但对于高负载服务器,正如我所喜欢的,sed
因为它非常快且可扩展,我经常使用这个:
while read event target lost ; do
case $event in
NEW )
ip2int $target intTarget
((count[intTarget]++))
...
esac
done < <(tail -f /path/logfile | sed -une '
s/^.*New incom.*from ip \([0-9.]\+\) .*$/NEW \1/p;
s/^.*Auth.*ip \([0-9.]\+\) failed./FAIL \1/p;
...
')