auditd是唯一能回溯“谁、何时、用什么进程改了文件”的工具,工作在内核系统调用层,捕获write、openat等真实操作并附带uid、pid、comm、exe、cwd等完整上下文。

查不到“谁改过”,说明你没用 auditd
Linux 默认不记录文件修改的进程来源,stat、ls -l、inotifywait 都只能告诉你“什么时候变过”或“现在谁在用”,但无法回溯“谁、何时、用什么进程写的”。真正能查到完整上下文(pid、comm、exe、uid、cwd)的,只有 auditd —— 它工作在内核系统调用层,捕获的是真实的 write、openat、renameat 等行为。
临时加一条规则试试:sudo auditctl -w /etc/hosts -p w -k hosts_write
然后 echo 一行进去:echo "127.0.0.2 test" | sudo tee -a /etc/hosts
再查:sudo ausearch -k hosts_write -i | head -10
-
-p w是关键:只加-p a(属性)或-p r(读)不会记录内容修改 -
-k标签比-f更可靠,尤其路径含软链接时 - 输出里
comm="tee"是命令名,exe="/usr/bin/tee"是真实可执行路径,cwd="/home/user"是当前目录 - 如果看到
comm="(unknown)",说明进程已退出,得靠exe和ppid向上追
文件还在被写,用 lsof 看“正在改”的进程
如果文件当前正被打开并写入(比如日志文件持续追加),lsof 能立刻定位活跃进程,但它看不到历史操作。
运行:sudo lsof /var/log/nginx/access.log
- 必须加
sudo,否则看不到 root 或其他用户的进程 - 看
FD列:带w或u(读写)表示正在写;DEL表示已删但仍被占用 - 路径必须写绝对路径,
lsof foo.log不会自动补当前目录 -
COMMAND是ps输出的 basename(如nginx),不是完整命令行
文件删了但空间没释放?查 (deleted) 句柄
常见于日志轮转后 df 显示磁盘满但 du 算不出大文件——其实是进程还在往已删文件的 inode 写数据。
查法一(推荐):sudo lsof +L1 | grep access.log
查法二(手动遍历):for pid in /proc/[0-9]*; do ls -l "$pid/fd" 2>/dev/null | grep -q "access.log.*deleted" && echo "$pid"; done
-
+L1是 lsof 内置开关,直接列出所有已删仍占句柄的文件 - 输出中
/var/log/nginx/access.log (deleted)后面的 PID 就是源头 - 对应 fd 链接在
/proc/<pid>/fd/</pid>下,readlink可确认真实路径 - 这类进程通常要发
SIGHUP或reopen信号,而非直接 kill
auditd 规则怎么存才不丢
auditctl 加的规则重启 auditd 或机器就没了。生产环境必须落盘为永久规则。
正确做法:echo "-w /etc/ssh/sshd_config -p wa -k sshd_conf" | sudo tee /etc/audit/rules.d/sshd.rulessudo augenrules --loadsudo auditctl -l | grep sshd_config
- 规则文件必须放在
/etc/audit/rules.d/下,且以.rules结尾 - 不能直接改
/etc/audit/audit.rules—— 它由augenrules自动生成,手动改会被覆盖 -
-p wa比单-p w多记 chmod/chown,适合配置文件监控 - 高 IO 目录慎用
-p rwxa,r会爆炸式打日志
auditd 是唯一能回答“谁、何时、用什么进程改了文件”的机制,其他方法全是间接推测或实时快照。配置错一个 -p 参数,日志里就根本不会出现写入事件——这点最容易被忽略。











