CentOS8下inotifywait接while循环被跳过无法监听文件事件问题
inotifywait 启动后直接退出不监听事件的解决方法
问题原因
CentOS 8 Stream 官方源自带的inotify-tools-3.14版本存在已知bug:inotifywait默认是单次监听模式(监听到一次事件就退出),在这个模式下如果程序的标准输出不是直连终端(比如通过管道传给while循环、输出重定向到文件),就会在打印完Watches established.完成监听初始化后直接退出,不会等待事件触发,这就是脚本没有进入等待逻辑、直接执行后续echo语句的核心原因。
另外你当前用sh test.sh的方式执行脚本,会让脚本在POSIX兼容模式下运行,虽然不是这次问题的诱因,但脚本首行声明的是bash解释器,建议后续用chmod +x test.sh && ./test.sh或者bash test.sh的方式执行,避免不必要的兼容问题。
修复方法
根据监听需求选对应的改法即可:
持续监听文件修改事件
给inotifywait加上-m参数开启持续监听模式,就能绕开这个bug,修改后的脚本:
#!/bin/bash inotifywait -m -e modify ./test.txt | while read dirname eventlist filename do echo "Event catch!" done echo "I am doing next thing"
注意:这种写法脚本会一直驻留在监听逻辑里,只有手动终止脚本才会走到最后一行echo,如果需要捕获到事件后就继续执行后续逻辑,用下面的单次监听写法。
仅监听第一次修改事件就执行后续逻辑
用持续监听模式,捕获到第一次事件后主动终止inotifywait进程再退出循环即可:
#!/bin/bash inotifywait -m -e modify ./test.txt | while read dirname eventlist filename do echo "Event catch!" # 杀掉当前脚本启动的inotifywait进程 pkill -P $$ inotifywait break done echo "I am doing next thing"
如果不想修改脚本参数,也可以把inotify-tools升级到3.20及以上版本,上游已经修复了单次模式下非终端输出直接退出的bug。
额外排查项
如果改完还是无法正常捕获事件,检查两个点:
- 被监听的
test.txt必须存放在本地文件系统(ext4、xfs等)上,NFS、CephFS等网络文件系统不支持inotify事件机制,无法正常触发回调 - 执行
sysctl fs.inotify.max_user_watches查看系统inotify监听句柄上限,如果值低于8192,可以执行sysctl -w fs.inotify.max_user_watches=524288临时调大,要永久生效就把fs.inotify.max_user_watches=524288写入/etc/sysctl.conf后执行sysctl -p加载配置
内容的提问来源于stack exchange,提问作者TyeolRik
相关产品推荐
相关产品推荐

