直接用 grep 和 awk 清洗 auditd 日志高效轻量,需分层剥离:先用 grep 锁定 syscall 等关键事件类型,再用 awk 按 = 和引号解析嵌套字段,结合时间过滤与结构化输出生成可读报告。

直接用 grep 和 awk 清洗 auditd 日志是高效且轻量的做法。auditd 原生日志(如 /var/log/audit/audit.log)虽为文本,但每行结构松散、字段嵌套、时间戳非标准、关键词混杂在括号与引号中,属于典型的“半结构化”数据。高阶组合的关键不是硬拼命令,而是分层剥离:先用 grep 定向截取目标事件类型,再用 awk 按语义字段切分并提取真实值。
聚焦关键事件类型,避免全量解析
auditd 日志包含 SYSCALL、PATH、CWD、EXECVE 等多种事件类型,混在一起会干扰后续处理。应优先用 grep 锁定核心行为:
-
只取系统调用事件:
grep "type=SYSCALL" /var/log/audit/audit.log -
过滤出 execve 调用(如可疑进程启动):
grep "type=SYSCALL.*execve" /var/log/audit/audit.log -
排除低价值日志(如 auditctl 自身调用):
grep "type=SYSCALL" audit.log | grep -v "comm=\"auditctl\""
用 awk 解析字段值,绕过空格陷阱
auditd 行内字段以空格分隔,但值本身常含空格(如 cwd="/home/user/dir with space"),不能简单用 $n 提取。正确做法是让 awk 按 = 和引号识别键值对:
-
提取执行命令的完整路径(
exe字段):awk -F'=' '/exe="/ {gsub(/"/,"",$2); print $2}' -
提取原始用户 ID(
auid)和有效用户 ID(uid):awk '{for(i=1;i -
同时提取多个字段并格式化输出:
awk -F'=' '/comm=/ && /exe=/ && /auid=/ {for(i=1;i(需配合字段定位逻辑)
还原时间戳并做范围筛选
auditd 时间戳是秒+毫秒整数(如 msg=audit(1747785600.123:45678)),需转为可读格式。可在 awk 中调用 strftime(GNU awk 支持):
-
提取并转换时间戳:
awk -F'[(:]' '/msg=audit/ {cmd="date -d @\""$2"\" +\"%Y-%m-%d %H:%M:%S\" 2>/dev/null"; cmd | getline dt; close(cmd); print dt, $0}' audit.log -
只保留今天的数据(结合系统时间):
awk -F'[(:]' -v today="$(date -d 'today' +%s)" '/msg=audit/ {if($2 >= today) print $0}' audit.log -
筛选最近一小时的 execve 行:
awk -F'[(:]' -v cutoff=$(($(date -d '1 hour ago' +%s))) '/msg=audit/ {if($2 > cutoff && /execve/) print $0}' audit.log
合并清洗结果,生成结构化输出
最终目标是把原始 audit.log 行变成带表头的 CSV 或对齐列,方便人工排查或导入分析工具:
-
生成带字段名的简洁报告:
grep "type=SYSCALL.*execve" audit.log | awk -F'=' '{auid="";exe="";comm=""; for(i=1;i -
按 auid 分组统计可疑命令次数:
... | awk -F',' '{count[$1","$2]++} END {for (i in count) print i","count[i]}' | sort -t',' -k3 -nr -
导出为制表符分隔,兼容 Excel:
... | awk -v OFS='\t' '{print $1,$2,$3}' > clean_audit.tsv
不复杂但容易忽略的是字段边界处理和时间精度对齐。auditd 日志不是纯日志,它是系统调用的原始快照,清洗本质是语义还原——用 grep 定向,用 awk 解码,中间少一层 shell 变量中转,就少一分失真。











