inotifywait连续事件触发问题:如何正确处理后续触发的事件?
问题
我用以下循环监控文件的close_write事件:
while inotifywait -qq --event close_write "$filebs" "$filevp"; do do_something done
问题是有时会连续触发两个事件,当代码在处理第一个事件的do_something时,第二个事件已经触发。我可以接受处理这两个事件,也可以接受仅处理第二个事件,但绝对不能只处理第一个事件。请问该如何实现?我猜想是不是需要用inotifywatch把事件存入缓冲区再读取?
解决方案
方案一:处理所有触发的事件
如果希望所有连续触发的事件都被处理、不遗漏,可以让inotifywait持续运行(添加-m参数),通过管道将事件输出传给循环逐个处理。即使do_something执行期间有新事件触发,inotifywait会把事件暂存在管道缓冲区,等当前do_something完成后继续处理下一个。
修改后的代码:
inotifywait -m -qq --event close_write "$filebs" "$filevp" | while read -r _; do do_something done
注:read -r _用来忽略inotifywait输出的事件详情,仅捕获“有事件触发”的信号。如果需要用到事件具体信息,可将_替换为对应变量(比如event_info)。
方案二:仅处理连续事件中的最后一个
如果希望连续触发多个事件时只处理最后一个(避免重复执行do_something),可以通过定时器防抖实现:每次事件触发时重置定时器,只有当定时器到期后没有新事件,才执行do_something。
修改后的代码:
# 带防抖逻辑的事件处理函数 handle_event() { # 杀掉之前的定时器进程(如果存在) [ -n "$sleep_pid" ] && kill "$sleep_pid" 2>/dev/null # 启动新定时器,延迟0.5秒执行do_something(可根据需求调整延迟时长) sleep 0.5 && do_something & sleep_pid=$! } # 持续监控事件,每次触发都调用防抖函数 inotifywait -m -qq --event close_write "$filebs" "$filevp" | while read -r _; do handle_event done
这个逻辑下,连续触发的事件会不断重置定时器,只有最后一次事件触发后,等待指定延迟时间内没有新事件,才会执行do_something。
关于inotifywatch的说明
inotifywatch主要用于统计事件发生的次数,并不适合捕获事件并触发处理逻辑,因此不需要用它来做缓冲区存储,用inotifywait的持续监控模式即可解决问题。
内容的提问来源于stack exchange,提问作者robertspierre
相关产品推荐
相关产品推荐

