如何用 Shell 脚本实现对指定目录的实时监控,并在检测到文件或子目录发生变化时把相关事件写入日志文件?请给出脚本实现思路与关键代码。
考察说明
考查候选人使用 Shell 脚本进行文件系统事件监控与日志记录的能力。
回答思路
- 【回答框架 1】核心思路是轮询目录状态或利用 inotify 机制。轮询方案用 find 或 ls 记录文件列表、大小、修改时间,定期比对差异;inotify 方案用 inotifywait 监听 create、modify、delete、move 等事件,实时性更好。
- 【回答框架 2】轮询实现:先建立基线快照,例如用 find 输出路径、大小、mtime 到临时文件,循环 sleep 后重新生成快照,用 diff 或 comm 对比,将新增、删除、修改条目按时间戳追加到日志。注意处理文件名含空格或换行的情况,建议用 null 分隔。
- 【回答框架 3】inotify 实现:使用 inotifywait -m -r -e modify,create,delete,move 目录,逐行读取输出,解析事件类型和文件路径,格式化后写入日志。需处理事件风暴,可加缓冲或去重。
- 【回答框架 4】日志记录要包含时间、事件类型、文件路径,可考虑轮转日志避免无限增长。脚本需处理目录不存在、权限不足等异常,并支持通过 trap 优雅退出。
- 【回答框架 5】选择依据:目录小且变化不频繁用轮询简单可靠;要求实时或目录大用 inotify 减少开销。生产环境可结合 systemd 或 cron 管理脚本生命周期。
- 【关键点 1】轮询方案用快照对比,注意处理文件名特殊字符。
- 【关键点 2】inotifywait 提供实时事件,需处理事件风暴。
- 【关键点 3】日志格式统一,包含时间、事件、路径,并考虑日志轮转。
- 【关键点 4】脚本需处理目录不存在、权限不足等异常。
- 【关键点 5】根据实时性要求和目录规模选择轮询或 inotify。
- 【易错点 1】轮询间隔过短导致高负载,过长则漏检快速变化。
- 【易错点 2】inotify 对递归监控有目录数量限制,可能需调整系统参数。
- 【易错点 3】直接拼接文件名到命令可能导致注入或解析错误,应使用 null 分隔或数组。