我正在尝试编写一个用于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 脚本来代替我的回声命令。请注意各种撇号和引号。