网站文件哈希监控脚本,检测文件改动告警
网站文件被悄悄改动,往往要等页面被挂马或功能出错才会发现。
用哈希监控脚本可以解决这个问题:首次记录每个文件的哈希值作为基线,之后定时重新计算并比对,一旦有变化就写日志或发告警。
本文面向零基础用户,给出可直接运行的 Shell 脚本和定时任务配置,照着做就能完成网站文件改动检测。
先确认环境和监控范围
开始前需要一台 Linux 服务器,并且有 root 或可读网站目录的账号。
把要做哈希监控的目录确定下来,比如 /www/wwwroot/example,不要一上来就监控整个 /,否则文件多、耗时长,输出也难读。
检查基础命令是否可用:
which sha256sum find crontab
三条命令都返回路径说明环境没问题。
如果缺少 sha256sum,可以在 Debian/Ubuntu 上执行 apt install coreutils,在 CentOS 上执行 yum install coreutils。
脚本运行需要两个目录:一个存放基线文件,一个存放日志。
建议统一放在 /opt/file_monitor 下,权限设为仅管理员可读写。
生成哈希基线并编写监控脚本
第一次运行必须先生成基线,否则脚本没有对比对象。
创建目录和基线命令如下:
mkdir -p /opt/file_monitor
cd /opt/file_monitor
find /www/wwwroot/example -type f -exec sha256sum {} \; > baseline.sha256
生成后打开 baseline.sha256 检查几行内容,格式应为“哈希值 + 文件路径”。
如果文件数量很多,可以先用 wc -l baseline.sha256 看行数,确认没有明显遗漏。
接着创建监控脚本 /opt/file_monitor/check_files.sh:
#!/bin/bash
MONITOR_DIR="/www/wwwroot/example"
HASH_FILE="/opt/file_monitor/baseline.sha256"
LOG_FILE="/opt/file_monitor/change.log"
TMP_FILE="/opt/file_monitor/current.sha256"
find "$MONITOR_DIR" -type f -exec sha256sum {} \; > "$TMP_FILE"
if ! diff -q "$HASH_FILE" "$TMP_FILE" > /dev/null; then
echo "[$(date '+%F %T')] 检测到文件改动" >> "$LOG_FILE"
diff "$HASH_FILE" "$TMP_FILE" >> "$LOG_FILE"
cp "$TMP_FILE" "$HASH_FILE"
else
echo "[$(date '+%F %T')] 文件无变化" >> "$LOG_FILE"
fi
脚本逻辑是:重新计算当前哈希,与基线比对;
有差异就记录时间、具体差异行,并用新哈希覆盖基线,避免同一处改动反复告警。
赋值权限后手动跑一次:
chmod +x /opt/file_monitor/check_files.sh
/opt/file_monitor/check_files.sh
cat /opt/file_monitor/change.log
日志里出现“文件无变化”说明脚本工作正常。
接入定时任务和告警方式
手动运行没问题后,用 cron 定时执行。
执行 crontab -e,加入一行表示每 10 分钟检查一次:
*/10 * * * * /bin/bash /opt/file_monitor/check_files.sh
保存后可用 crontab -l 确认任务已写入。
cron 默认不会把输出发到终端,因此告警主要看日志文件。
需要主动通知时,可以在脚本的改动分支中追加邮件或 webhook 命令,例如:
mail -s "网站文件改动告警" admin@yourdomain.com < "$LOG_FILE"
使用前先用 mail 命令测试一次收信是否正常。
也可以把 change.log 交给宝塔面板的文件管理器定期查看,或在宝塔的“计划任务”中新建 Shell 脚本任务,把脚本路径填进去,执行周期设为 10 分钟。
需要重点留意:告警内容里应包含具体文件路径,否则收到通知也不知道改了什么。
脚本里 diff 输出的行号能直接定位差异位置。
避免误报和常见问题处理
网站运行过程中会有正常写入,比如缓存目录、上传目录、日志文件。
如果监控范围包含这些目录,会频繁告警。
建议在 find 命令中排除它们:
find "$MONITOR_DIR" -type f \
-not -path "*/cache/*" \
-not -path "*/uploads/*" \
-not -path "*/runtime/*" \
-exec sha256sum {} \; > "$TMP_FILE"
排除后需要重新生成一次基线,否则旧基线仍包含被排除的文件,比对结果会不一致。
另一个常见问题是权限不足,脚本读不到某些文件时 sha256sum 会输出错误信息。
可以把标准错误重定向到日志:
find "$MONITOR_DIR" -type f -exec sha256sum {} \; 2>> /opt/file_monitor/error.log > "$TMP_FILE"
如果日志里频繁出现“文件无变化”占满磁盘,可以只保留改动记录,把无变化分支的 echo 删掉,或定期清理日志。
验证告警是否真的生效
配置完成后不要只看脚本“跑过了”就结束。
手动制造一次改动来验证:
echo "test" >> /www/wwwroot/example/index.php
/opt/file_monitor/check_files.sh
tail -n 5 /opt/file_monitor/change.log
日志中应出现“检测到文件改动”以及 index.php 对应的差异行。
确认后把测试内容删掉,再执行一次脚本,让基线回到正常状态。
验证通过后,建议每周抽查一次 change.log,确认没有异常文件被改动,也确认告警渠道仍然可用。
哈希监控解决的是“文件有没有变”,不能替代杀毒和权限管理,两者配合使用效果更好。
关于文件哈希监控的常见疑问
如果网站文件很多,脚本会不会太慢?
这取决于文件数量和磁盘性能。
可以先用 time /opt/file_monitor/check_files.sh 测一次耗时,再决定检查频率,通常 10 到 30 分钟一次比较稳妥。
监控到改动后应该先做什么?
先看差异文件路径和改动时间,判断是程序正常更新、缓存写入还是异常篡改。
确认是正常更新后,让脚本自动更新基线即可;
如果是异常改动,先备份现场再处理。
能不能只监控部分文件?
可以。
把 MONITOR_DIR 改成更具体的目录,或在 find 中增加 -name "*.php" 之类条件,只监控关键类型文件,能明显减少误报。