Linux tetragon 的 export / process_exec / process_exit 事件观测模板

2次阅读

tetragon 默认只捕获 execve 系统调用,不捕获 shell 内建命令(如 cd、export)、重定向或管道中的子进程;process_exit 的 status 需右移 8 位才得真实退出码;export 变量变更无法直接观测,需通过 env 字段或 fork/exec 联动间接推断;process_fork 应启用以构建完整进程关系链。

Linux tetragon 的 export / process_exec / process_exit 事件观测模板

为什么 process_exec 事件没抓到你想要的命令?

Tetragon 默认只捕获 execve 系统调用,不包括 shell 内建命令(如 cdexport)、重定向或管道中的子进程。它看到的是内核真正执行的二进制,不是你敲的那行 bash 命令。

  • 如果你运行 echo $PATH,Tetragon 不会触发 process_exec —— 因为 echo 是 shell 内建或已缓存的,且变量展开发生在用户态
  • process_exec 只在新进程真正 execve() 时发出,比如 ls -l/bin/sh -c "sleep 1"
  • 某些容器运行时(如 containerd)可能用 clone()+execve 组合,但 Tetragon 仍只对后者打点
# 正确能捕获的示例: $ /bin/bash -c "date" # Tetragon 会报告 /bin/bash 和 /bin/date 两次 process_exec

process_exit 的 status 字段怎么解读?

process_exit 里的 status 不是直接的退出码,而是原始 waitpid 返回的 16 位整数,需用 WEXITSTATUS() 宏解包(即 status >> 8)。直接当退出码用会错。

  • 若进程被信号终止(如 kill -9),status & 0x7F 是信号编号,WIFEXITED(status) 为 false
  • Tetragon 导出的 json 中,status 是十进制整数,比如 256 表示正常退出码 1(256 = 1
  • 未设置 wait4() 或子进程变成僵尸前就退出,process_exit 可能延迟或丢失(尤其高并发短命进程)

常见误读:"status": 35584 → 实际退出码是 35584 >> 8 == 139,对应 SIGSEGV(139 = 128 + 11)

如何让 export 变量变更也被观测到?

Tetragon 本身不监听环境变量修改,因为 export 是 shell 内建操作,不触发系统调用。要间接捕获,得靠上下文关联:

  • process_exec 事件中检查 env 字段(需启用 env probe,且进程 exec 时带完整环境)
  • 启用 process_fork + process_exec 联动:父进程(如 bash)fork 后,子进程 exec 前的环境可反映 export 结果
  • 更可靠的方式是用 eBPF 额外挂载 tracepoint:syscalls:sys_enter_execve 并读取 argvenvp,但 Tetragon 默认不导出全部 envp(默认截断)

注意:env 字段在 Tetragon 输出里是数组,但只包含 exec 时传入的 key=value 字符串,不会告诉你哪条 export 语句改了它

模板里要不要加 process_fork

加,但别只为“看到 fork”。它的价值在于补全父子关系链,否则 process_execprocess_exit 是孤立事件,无法判断谁启动了谁、谁等谁退出。

  • process_fork 提供 parent_pidchild_pid,配合 process_execpid 可构建进程树
  • 不加 fork 模板时,你看到一个 curl 的 exec 和 exit,但不知道它是 cron 启的还是 systemd 启的
  • 性能影响极小(fork 是轻量系统调用),但日志量会上升;若只关心顶层容器进程,可过滤掉 UID > 0 的 fork(排除普通用户进程干扰)

典型漏配:只监听 exec/exit,结果发现某个 process_exit 找不到对应的 exec —— 很可能是 exec 发生在 fork 之后、而 fork 事件被过滤掉了

text=ZqhQzanResources