如何通过Rust结合ptrace追踪Docker容器内系统调用?
容器内进程系统调用追踪方案(Rust + ptrace)
一、主机端定位容器内进程的全局PID
Docker容器基于PID Namespace实现进程隔离,容器内的PID是独立于主机的,要追踪必须先找到进程对应的主机全局PID,方法如下:
- 获取容器init进程的主机PID(容器内PID=1对应的主机PID):
docker inspect -f '{{.State.Pid}}' <container-id> - 进入容器的PID Namespace查看内部进程列表:
sudo nsenter -t <容器init的主机PID> -p ps aux - 匹配容器内PID到主机全局PID:
找到目标进程的容器内PID后,在主机上执行:
输出路径中的数字即为该进程的主机全局PID(例如sudo grep -l '<容器内PID>' /proc/*/status/proc/1234/status中的1234)
二、解决PID不符问题
你当前追踪的是docker exec进程的主机PID,而非容器内测试程序的PID。修正方法:
- 先按上述步骤找到测试程序对应的主机全局PID
- 用ptrace直接attach到这个PID,而非
docker exec的进程ID
三、捕获mkdir/rmdir系统调用的注意事项
- 系统调用号的实际映射:部分libc封装的函数会调用底层不同的系统调用,比如
mkdir可能实际调用mkdirat(x86_64系统调用号258),可先在容器内用strace ./测试程序确认实际触发的系统调用。 - ptrace选项配置:必须开启
TRACESYSGOOD标记,方便区分系统调用触发的信号与普通信号。 - 事件处理逻辑:需要分别处理
SyscallEnter和SyscallExit事件,不能只监听进程启动/退出。
四、Rust + pete库实现示例
use pete::{Ptracer, TraceOptions, Event}; use nix::sys::ptrace; use nix::unistd::Pid; fn main() -> Result<(), Box<dyn std::error::Error>> { // 替换为目标进程的主机全局PID let target_pid = Pid::from_raw(1234); let mut tracer = Ptracer::new(); // 开启系统调用追踪标记,便于区分信号类型 tracer.set_options(TraceOptions::TRACESYSGOOD)?; // 附加到目标进程 tracer.attach(target_pid)?; loop { match tracer.wait()? { // 捕获系统调用进入事件 Event::SyscallEnter(pid, regs) => { let syscall_num = regs.rax as i32; // x86_64系统调用号:mkdir=83, rmdir=84, mkdirat=258 match syscall_num { 83 => println!("[PID {}] 进入mkdir调用", pid), 84 => println!("[PID {}] 进入rmdir调用", pid), 258 => println!("[PID {}] 进入mkdirat调用", pid), _ => {} } // 继续追踪下一个系统调用 ptrace::syscall(pid, None)?; } // 捕获系统调用退出事件 Event::SyscallExit(pid, regs) => { let syscall_num = regs.rax as i32; match syscall_num { 83 => println!("[PID {}] mkdir调用完成,返回值: {}", pid, regs.rax), 84 => println!("[PID {}] rmdir调用完成,返回值: {}", pid, regs.rax), 258 => println!("[PID {}] mkdirat调用完成,返回值: {}", pid, regs.rax), _ => {} } ptrace::syscall(pid, None)?; } // 进程退出时终止追踪 Event::Exit(pid, status) => { println!("[PID {}] 进程退出,状态码: {}", pid, status); break; } // 其他事件(如进程暂停),继续执行 _ => ptrace::cont(target_pid, None)?, } } Ok(()) }
五、运行注意事项
- 必须以root权限运行程序(或给程序添加
CAP_SYS_PTRACE权限),否则无法attach到目标进程:sudo ./target/debug/your-program
内容的提问来源于stack exchange,提问作者Zheng Wei
相关产品推荐
相关产品推荐

