github: cmdcat
原理就是通过LD_PRELOAD
环境变量 hook 掉 exec 和 fork 调用,然后可以将这些调用的参数和环境变量通过进程通信的方式传回给 cmdcat 进程。
写这个工具的原因是有的 C/C++项目的构建比较复杂,用这个工具可以知道某个对象是怎么构建出来的。并且 cmdcat 也可以用来生成compile_commands.json
,借鉴了bear。
cmdcat 的输出是 json 格式,描述创建后代进程的命令行参数和环境变量。下面是执行cmdcat make
的一部分输出样例:
...
{
"args": {
"0": "-s",
"1": "-f",
"2": "CMakeFiles/execfork.dir/build.make",
"3": "CMakeFiles/execfork.dir/build"
},
"children": [],
"cmd": "/usr/bin/make",
"cwd": "/home/prack/cmdcat/build",
"envs": {
"AUTOFEATURE": "true autotest",
"BASH_IT": "/home/prack/conf/otherRepo/bash-it",
"BASH_IT_THEME": "bobby",
"CMDCAT_SERVER_DOMAIN": "AF_UNIX",
"CMDCAT_SERVER_PATH": "/tmp/socket-yyjhgqrwdkxwzaxxirgcp",
"CMDCAT_SERVER_PORT": "0",
"CMDCAT_SERVER_TYPE": "SOCK_DGRAM",
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
"GIT_HOSTING": "[email protected]",
"GREP_COLOR": "1;33",
"HISTCONTROL": "ignorespace:erasedups",
"HISTSIZE": "5000",
"HOME": "/home/prack",
"IRC_CLIENT": "irssi",
"LANG": "en_US.UTF-8",
"LD_PRELOAD": "/tmp/libccat_yyjhgqrwdkxwzaxxirgc.so",
"LOGNAME": "prack",
"LSCOLORS": "Gxfxcxdxdxegedabagacad",
"MAKEFLAGS": "s",
"MAKELEVEL": "2",
"MAKE_TERMERR": "/dev/pts/13",
"MFLAGS": "-s",
"MOTD_SHOWN": "pam",
"OLDPWD": "/home/prack/cmdcat",
"PATH": "/home/prack/.local/bin:/home/prack/local/bin:/home/prack/.node/bin:/home/prack/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin",
"PWD": "/home/prack/cmdcat/build",
"SCM_CHECK": "true",
"SHELL": "/bin/bash",
"SHLVL": "1",
"SSH_CLIENT": "192.168.44.1 54209 22",
"SSH_CONNECTION": "192.168.44.1 59849 192.168.44.43 22",
"SSH_TTY": "/dev/pts/0",
"TERM": "screen-256color",
"TERM_PROGRAM": "tmux",
"TERM_PROGRAM_VERSION": "3.2a",
"TMUX": "/tmp/tmux-1000/default,2768,1",
"TMUX_PANE": "%20",
"TMUX_PLUGIN_MANAGER_PATH": "/home/prack/.tmux/plugins/",
"TODO": "t",
"USER": "prack",
"XDG_DATA_DIRS": "/usr/local/share:/usr/share:/var/lib/snapd/desktop",
"XDG_RUNTIME_DIR": "/run/user/1000",
"XDG_SESSION_CLASS": "user",
"XDG_SESSION_ID": "4",
"XDG_SESSION_TYPE": "tty",
"_": "/home/prack/local/bin/cmdcat"
},
"fullcmd": "/usr/bin/make -s -f CMakeFiles/execfork.dir/build.make CMakeFiles/execfork.dir/build",
"history": {
"0": {
"argv": {
"0": "-s",
"1": "-f",
"2": "CMakeFiles/Makefile2",
"3": "all"
},
"cmd": "/usr/bin/make"
}
},
"nchild": 0,
"pid": 330249,
"ppid": 330215,
"uid": 39
},
{
"args": {
"0": "-c",
"1": "/usr/bin/cmake -E cmake_echo_color --switch= --progress-dir=/home/prack/cmdcat/build/CMakeFiles --progress-num=8,9 \"Built target execfork\""
},
"children": [
{
"args": {
"0": "-E",
"1": "cmake_echo_color",
"2": "--switch=",
"3": "--progress-dir=/home/prack/cmdcat/build/CMakeFiles",
"4": "--progress-num=8,9",
"5": "Built target execfork"
},
"children": [],
"cmd": "/usr/bin/cmake",
"cwd": "/home/prack/cmdcat/build",
"envs": {
"AUTOFEATURE": "true autotest",
"BASH_IT": "/home/prack/conf/otherRepo/bash-it",
"BASH_IT_THEME": "bobby",
"CMDCAT_SERVER_DOMAIN": "AF_UNIX",
"CMDCAT_SERVER_PATH": "/tmp/socket-yyjhgqrwdkxwzaxxirgcp",
"CMDCAT_SERVER_PORT": "0",
"CMDCAT_SERVER_TYPE": "SOCK_DGRAM",
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
"GIT_HOSTING": "[email protected]",
"GREP_COLOR": "1;33",
"HISTCONTROL": "ignorespace:erasedups",
"HISTSIZE": "5000",
"HOME": "/home/prack",
"IRC_CLIENT": "irssi",
"LANG": "en_US.UTF-8",
"LD_PRELOAD": "/tmp/libccat_yyjhgqrwdkxwzaxxirgc.so",
"LOGNAME": "prack",
"LSCOLORS": "Gxfxcxdxdxegedabagacad",
"MAKEFLAGS": "s",
"MAKELEVEL": "2",
"MAKE_TERMERR": "/dev/pts/13",
"MFLAGS": "-s",
"MOTD_SHOWN": "pam",
"OLDPWD": "/home/prack/cmdcat",
"PATH": "/home/prack/.local/bin:/home/prack/local/bin:/home/prack/.node/bin:/home/prack/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin",
"PWD": "/home/prack/cmdcat/build",
"SCM_CHECK": "true",
"SHELL": "/bin/bash",
"SHLVL": "1",
"SSH_CLIENT": "192.168.44.1 54209 22",
"SSH_CONNECTION": "192.168.44.1 59849 192.168.44.43 22",
"SSH_TTY": "/dev/pts/0",
"TERM": "screen-256color",
"TERM_PROGRAM": "tmux",
"TERM_PROGRAM_VERSION": "3.2a",
"TMUX": "/tmp/tmux-1000/default,2768,1",
"TMUX_PANE": "%20",
"TMUX_PLUGIN_MANAGER_PATH": "/home/prack/.tmux/plugins/",
"TODO": "t",
"USER": "prack",
"XDG_DATA_DIRS": "/usr/local/share:/usr/share:/var/lib/snapd/desktop",
"XDG_RUNTIME_DIR": "/run/user/1000",
"XDG_SESSION_CLASS": "user",
"XDG_SESSION_ID": "4",
"XDG_SESSION_TYPE": "tty",
"_": "/home/prack/local/bin/cmdcat"
},
"fullcmd": "/usr/bin/cmake -E cmake_echo_color --switch= --progress-dir=/home/prack/cmdcat/build/CMakeFiles --progress-num=8,9 Built target execfork",
"history": {
"0": {
"argv": {
"0": "-c",
"1": "/usr/bin/cmake -E cmake_echo_color --switch= --progress-dir=/home/prack/cmdcat/build/CMakeFiles --progress-num=8,9 \"Built target execfork\""
},
"cmd": "/bin/sh"
}
},
"nchild": 0,
"pid": 330251,
"ppid": 330250,
"uid": 41
}
],
ubuntu20.04 的用户可以直接下载构建好的二进制文件release,其他 linux 系统的没有验证过。
1
sakeven 2023-08-02 11:38:29 +08:00
用 ebpf 跟踪更好。LD_PRELOAD 对静态链接无效。
|
2
julyclyde 2023-08-02 13:09:14 +08:00
重新发明了世界
用 cgroups 不就得了 |
3
err1y 2023-08-02 17:53:02 +08:00 via iPhone
类似 strace
|
4
weiwenhao 2023-08-02 18:02:19 +08:00
cmdcat A -> B, B 启动 C 之后,B 自己退出, 然后 C 再次启动新的程序能够追踪到么。
|
6
fuis 2023-08-03 14:00:03 +08:00
|