Shell脚本如何监控关键目录变更:实战指南与原理剖析
目录导读
- 为什么需要监控关键目录变更?
- 监控核心机制:inotify与轮询的对比
- 实战:编写一个高性能的目录监控Shell脚本
- 高级技巧:过滤噪音与告警集成
- 常见问题与解答
- 总结与最佳实践
为什么需要监控关键目录变更?
在服务器运维中,/etc、/var/www、/data/db等关键目录的意外变更可能引发严重问题:配置文件被篡改、网站文件被植入恶意代码、数据库文件异常删除,通过Shell脚本监控目录变更,可以:

- 实时发现入侵行为:当攻击者植入后门或修改系统配置时,立即触发告警
- 捕捉运维误操作:比如误删文件、错误修改权限等
- 审计文件完整性:配合备份策略,记录每次变更的详细信息
问:为什么不用现成的监控工具(如Tripwire)?
答:Shell脚本更轻量,易于集成到现有运维体系,且能灵活定制告警逻辑,适合对性能要求较高的场景。
监控核心机制:inotify与轮询的对比
| 机制 | 原理 | 适用场景 | 资源消耗 |
|---|---|---|---|
| inotify | 内核级文件事件监听 | 实时监控、高频率变更 | 极低(事件驱动) |
| 轮询(cron+find) | 定期扫描目录状态 | 低频监控、兼容老旧系统 | 高(周期扫盘) |
推荐方案:优先使用inotify(Linux 2.6.13+内核支持),如果系统不支持(如某些容器环境),则使用轮询作为降级方案。
问:inotify能监控子目录递归吗?
答:可以,通过inotifywait的-r参数实现递归监听,但注意要设置--monitor保持进程常驻。
实战:编写一个高性能的目录监控Shell脚本
以下脚本使用inotify监控/etc目录,记录变更日志并发送邮件告警:
#!/bin/bash
# 配置区
MONITOR_DIR="/etc"
LOG_FILE="/var/log/dir_monitor.log"
EMAIL_TO="admin@example.com"
EXCLUDE_PATTERN="\.(swp|~)$" # 忽略临时文件
# 依赖检查
if ! command -v inotifywait &> /dev/null; then
echo "Error: inotify-tools not installed. Run: apt install inotify-tools"
exit 1
fi
# 监控主逻辑
inotifywait -m -r --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %w%f %e' \
"$MONITOR_DIR" | while read datetime file event
do
# 过滤排除模式
if [[ "$file" =~ $EXCLUDE_PATTERN ]]; then
continue
fi
# 记录日志
echo "[$datetime] $event: $file" >> "$LOG_FILE"
# 对关键变更(如MODIFY, DELETE)发送告警
case "$event" in
MODIFY|DELETE|CREATE|MOVED_TO|MOVED_FROM)
mail -s "ALERT: $event on $file" "$EMAIL_TO" <<< \
"$(hostname) - $event detected on $file at $datetime"
;;
esac
done
脚本关键点解析:
-m:保持监听模式-r:递归子目录--timefmt:自定义时间格式--format:输出格式(时间、路径、事件类型)- 性能优化:通过正则排除
.*.swp等临时文件,避免日志风暴
问:如果监控目录有大量文件(如10万+),inotify能扛住吗?
答:默认inotify watch数量有限(/proc/sys/fs/inotify/max_user_watches),需调大:echo 65536 > /proc/sys/fs/inotify/max_user_watches,另外建议拆分监控多个子目录。
高级技巧:过滤噪音与告警集成
1 屏蔽高频无效事件
- 忽略
ACCESS和CLOSE_NOWRITE事件(读操作无意义) - 对
MODIFY事件增加300ms去重窗口(防止编辑器保存时多次触发)
# 使用flock实现简单去重 flock -w 0.3 /tmp/dir_monitor.lock -c "你的处理逻辑"
2 与第三方告警集成
- 企业微信机器人:
curl -X POST -H "Content-Type: application/json" -d '{"msgtype":"text","text":{"content":"变更告警"}}' https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx - 飞书/钉钉:类似webhook方式
- Prometheus告警:输出metrics到node_exporter
常见问题与解答
Q1:监控进程意外退出怎么办?
A:使用supervisor或systemd守护进程,并添加重启策略:
[Unit] Description=Directory Monitor [Service] ExecStart=/path/to/monitor_script.sh Restart=always RestartSec=10
Q2:如何监控网络挂载目录(NFS/SMB)?
A:inotify不支持网络文件系统,改为轮询方案:find /mnt/nfs_dir -newer /tmp/snapshot -type f。
Q3:监控日志占满磁盘怎么办?
A:配置logrotate轮转:
/var/log/dir_monitor.log {
daily
rotate 7
compress
missingok
notifempty
}
总结与最佳实践
- 优先inotify:性能好、实时性强,但注意调整内核参数
- 精确过滤:排除临时文件、系统扫描操作,告警才有价值
- 分级告警:DELETE/TRUNCATE为高优先级,CREATE/MODIFY为中优先级
- 定期测试:每月模拟一次变更,验证告警链路是否正常
- 日志审计:配合ELK或Loki进行集中分析,追溯历史变更
通过合理的Shell脚本设计,不仅能监控关键目录,还能成为入侵检测和合规审计的有力工具,监控的目的是发现问题,而不是制造噪音——每一次告警都应该是值得被关注的异常。