inotifywatch:文件轮换后继续观察

Nic*_*ick 4 logrotate inotify

我正在尝试编写一个脚本,用于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
Run Code Online (Sandbox Code Playgroud)

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

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

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

xhi*_*nne 6

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

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

使用--follow (-f),tail 默认跟在文件描述符之后,这意味着即使一个tail'ed 的文件被重命名,tail 也会con?继续追踪它的结束。当您确实想要跟踪文件的实际名称而不是文件描述符(例如日志轮换)时,这种默认行为是不可取的。在这种情况下使用 --follow=name 。这会导致 tail 以适应重命名、删除和创建的方式跟踪命名文件。

[更新]

使用示例:

tail -n0 -F my_file.log \
| while read -r log_line; do
    do_something_with "$log_line"
done
Run Code Online (Sandbox Code Playgroud)

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

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