特殊过滤
有些工具具有特殊的过滤功能,主要用例是跟踪运行在容器中的进程,但这些机制是通用的,可以在其他情况下也可以使用。
通过cgroups进行过滤
有些工具可以选择通过引用外部管理的固定BPF hash map来进行cgroup过滤。
命令示例:
# ./opensnoop --cgroupmap /sys/fs/bpf/test01
# ./execsnoop --cgroupmap /sys/fs/bpf/test01
# ./tcpconnect --cgroupmap /sys/fs/bpf/test01
# ./tcpaccept --cgroupmap /sys/fs/bpf/test01
# ./tcptracer --cgroupmap /sys/fs/bpf/test01
上面的命令将只显示属于某个cgroup的进程的结果,这些cgroup的id使用bpf_get_current_cgroup_id()
获取,并且在固定的BPF hash map中。
BPF hash map可以通过以下方式创建:
# bpftool map create /sys/fs/bpf/test01 type hash key 8 value 8 entries 128 \
name cgroupset flags 0
要在新的cgroup中创建shell,可以使用:
# systemd-run --pty --unit test bash
shell将运行在 /sys/fs/cgroup/unified/system.slice/test.service
目录管理的cgroup中。
可以使用name_to_handle_at()
系统调用来获取cgroup id。在examples/cgroupid中,你会找到一个获取cgroupid的程序示例。
# cd examples/cgroupid
# make
# ./cgroupid hex /sys/fs/cgroup/unified/system.slice/test.service
或者使用docker运行:
# cd examples/cgroupid
# docker build -t cgroupid .
# docker run --rm --privileged -v /sys/fs/cgroup:/sys/fs/cgroup \
cgroupid cgroupid hex /sys/fs/cgroup/unified/system.slice/test.service
这会以主机端序的十六进制字符串形式打印cgroup id,比如 77 16 00 00 01 00 00 00
# FILE=/sys/fs/bpf/test01
# CGROUPID_HEX="77 16 00 00 01 00 00 00"
# bpftool map update pinned $FILE key hex $CGROUPID_HEX value hex 00 00 00 00 00 00 00 00 any
现在systemd-run启动的shell在BPF hash map中有了它的cgroup id, bcc工具将显示这个shell的结果。可以从BPF hash map中添加和删除Cgroups条目,而无需重新启动bcc工具。
这个特性对于在外部项目中集成bcc工具非常有用。
按mount命名空间过滤
BPF hash map可以通过以下方式创建:
# bpftool map create /sys/fs/bpf/mnt_ns_set type hash key 8 value 4 entries 128 \
name mnt_ns_set flags 0
执行execsnoop
工具,只过滤/sys/fs/bpf/mnt_ns_set
中的mount命名空间:
# tools/execsnoop.py --mntnsmap /sys/fs/bpf/mnt_ns_set
在新的mount命名空间中启动一个终端:
# unshare -m bash
用上面终端的mount命名空间ID更新hash map:
FILE=/sys/fs/bpf/mnt_ns_set
if [ $(printf '\1' | od -dAn) -eq 1 ]; then
HOST_ENDIAN_CMD=tac
else
HOST_ENDIAN_CMD=cat
fi
NS_ID_HEX="$(printf '%016x' $(stat -Lc '%i' /proc/self/ns/mnt) | sed 's/.\{2\}/&\n/g' | $HOST_ENDIAN_CMD)"
bpftool map update pinned $FILE key hex $NS_ID_HEX value hex 00 00 00 00 any
在这个终端中执行命令:
# ping kinvolk.io
你将在execsnoop
终端上看到调用是如何被记录的:
# tools/execsnoop.py --mntnsmap /sys/fs/bpf/mnt_ns_set
[sudo] password for mvb:
PCOMM PID PPID RET ARGS
ping 8096 7970 0 /bin/ping kinvolk.io