inotifywatch:文件轮换后继续监视

inotifywatch:文件轮换后继续监视

我正在尝试编写一个用于inotifywatch监视日志文件中的更改的脚本。如果将特定消息写入日志文件,则应该触发特定功能。该脚本目前以这种基本形式存在:

while inotifywait -e modify /var/log/auth.log
do
  alert=$(tail -n1 /var/log/auth.log | grep -E -o ".{0,7}password")
  if [[ $alert == "Failed password" ]]
  then
   echo "FAILURE" >> test.log
  elif [[ $alert == "cepted password" ]]
  then
   echo "LOGIN" >> test.log
  fi
done

一切工作正常 - 直到所监视的日志文件inotifywatch出现为止旋转的。然后它就停止运作。我认为这是因为在轮换过程中,监视的文件被重命名,之后不再写入,并且在其位置创建了一个具有旧名称的新文件,该文件inotify从未被告知要监视。

我试图通过从使用切换inotifywatch到使用来规避这个问题tail -f,但同样的问题似乎也适用于此。

现在我意识到这可能可以通过创建一个巨大的if结构来解决,其中inotifywatch不仅监视modify,还监视文件创建并重新启动监视以进行修改。但我喜欢让事情变得简单,所以有人知道是否有更简单的方法? (拜托,不,我不想使用诸如fail2ban等预制解决方案——对我来说有趣的部分是用简单的工具自己创建这样的东西。)

答案1

inotify用于通过索引节点而不是名称来监视目录中的文件。当文件轮换时,其内容不再改变(除了一小段时间,直到重新加载守护程序以便它们使用新创建的日志文件)

AFAIK,tail -f使用 inotify 系统,所以它没有帮助。但是,如果您有一个可行的解决方案,tail -f则使用tail --follow=name(或tail -F) 如果您的版本支持此功能tail(POSIX tail 不支持此功能)。tail然后将监视由文件名标识的文件。以下是手册页的摘录:

使用 --follow (-f) 时,tail 默认跟随文件描述符,这意味着即使重命名有 tail 的文件,tail 将继续跟踪其结尾。当您确实想要跟踪文件的实际名称而不是文件描述符(例如,日志轮转)时,这种默认行为是不可取的。在这种情况下使用 --follow=name 。这会导致 tail 以适应重命名、删除和创建的方式跟踪命名文件。

[更新]

使用示例:

tail -n0 -F my_file.log \
| while read -r log_line; do
    do_something_with "$log_line"
done

由于管道的原因,while循环是在子进程中执行的,如果你想在循环外修改变量,可能会给你带来麻烦。如果您使用bash,您可能需要使用这种替代语法,它不会产生这种不良效果(但可读性较差):

while read -r log_line; do
    do_something_with "$log_line"
done < <(tail -n0 -F my_file.log)

答案2

可以用以下方法完成inotify等待一行:

inotifywait -e move_self -e modify -m /path/to/some/file | awk '$2=="MODIFY" {system("/bin/echo Yes")}'

-mflag 无限期地监视文件的事件移动_自我(允许监视文件或目录的名称更改)和调整,将输出传递给awk清除的命令移动_自我事件,执行里面的命令系统每个的括号调整事件。你必须编写你自己的 shell 脚本来代替我的回声命令。请注意各种撇号和引号。

相关内容