使用 head 和 fgrep 从数千个日志文件中找到正确的日志文件

使用 head 和 fgrep 从数千个日志文件中找到正确的日志文件

我有数千个日志文件 - 都非常大。其中之一将有我正在寻找的 IP 地址。我知道它很可能发生在文件顶部附近。我可以:

head -n 500 *.log | fgrep myip

我会看到“是”,它位于日志文件之一中。我如何确定是哪一个?由于文件大小的原因,不可能对所有文件的完整内容 (fgrep myip *.log) 进行 Grep 操作。

答案1

你只需 awk 就可以逃脱:

awk -v ip=127.0.0.1 'substr($0, ip) > 0 {print FILENAME ": " $0} FNR > 500 {nextfile}' *.log

如果在当前行中找到 IP,我们将打印它和文件名。如果当前文件 ( FNR) 的当前行号变得 > 500,我们将跳到下一个文件。

答案2

像这样的事情应该有帮助。

find . -iname "*.log" -print0 | xargs -0 -i{} bash -c 'echo "»»»File Name: {}«««"; head -n 500 {} | fgrep -B 501 myip'

它将生成一长串文件名,然后是最多 500 行找到的数据,然后是一长串文件名。您想要的文件名是紧邻一长串数据之前的文件名。

答案3

find -name \*.log -print0 |
  xargs -0 sh -c 'for i; do head -n 500 $i | fgrep -q myip && echo $i; done

这将找到所有以 结尾的文件名.log,并将该列表提供给xargs.和通常用于使用空字节来终止文件名,以保护包含空格的文件名(空字节永远不能在文件名中使用,因此是安全的分隔符)-print0xargs -0

xargs将运行后面给出的命令xargs及其参数,并使用一次命令调用中适合的文件名。在本例中,给出的命令是sh(shell),并且该 shell 被给予一个小的 shell 脚本来运行。

shell脚本基本上是:

for i; do
    head -n 500 $i | fgrep -q myip && echo $i
done

for i部分循环遍历给 shell 的所有参数,即所有文件名。对于每个文件名,它会获取前 500 行,并搜索给定的字符串。fgrep -q意味着 fgrep 一旦找到字符串就停止;如果找到该字符串,则给出退出状态“成功”,否则给出“失败”。最后,这&& echo $i意味着如果前面的命令具有“成功”状态,则执行回显,这意味着如果找到字符串则显示文件名。

答案4

我会:

  1. 循环遍历所有文件
  2. 抓取前 500 行
  3. 看看 IP 是否在这些行中
  4. 如果是,则打印文件名并结束循环

作为代码:

for f in ./*
do 
  head -n 500 "$f" | grep -qF myip && { printf "Found in: $f"; break; }
done

将其替换myip为您要查找的 IP。您可以创建一个函数(或 shell 脚本),将所需的 IP 作为参数进行搜索:

findlogip ()
{
    for f in ./*;
    do
        head -n 500 "$f" | grep -qF "$1" && {
            printf "Found in: $f\n";
            break
        };
    done
}

作为罗艾玛 评论,您可能需要小心搜索的 IP,以免意外匹配不同的 IP(示例中为 10.55.33.6,但匹配 110.55.33.68)。使用 GNU grep (假设,鉴于标记),您可以用标记包围给定的 IP 地址\b

...
head -n 500 "$f" | grep -q "\b$1\b" && ...
...

您删除-F(固定字符串)grep 选项,因为表达式不再是“固定”表达式,而是正则表达式。

相关内容