V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
ppxppx
V2EX  ›  分享创造

写了一个 Linux 命令行工具,用来执行一个命令并追踪后代进程的创建

  •  
  •   ppxppx · 269 天前 · 1289 次点击
    这是一个创建于 269 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 系统的没有验证过。

    6 条回复    2023-08-03 14:00:03 +08:00
    sakeven
        1
    sakeven  
       269 天前
    用 ebpf 跟踪更好。LD_PRELOAD 对静态链接无效。
    julyclyde
        2
    julyclyde  
       269 天前
    重新发明了世界

    用 cgroups 不就得了
    err1y
        3
    err1y  
       269 天前 via iPhone
    类似 strace
    weiwenhao
        4
    weiwenhao  
       269 天前
    cmdcat A -> B, B 启动 C 之后,B 自己退出, 然后 C 再次启动新的程序能够追踪到么。
    ppxppx
        5
    ppxppx  
    OP
       269 天前 via Android
    @weiwenhao 能的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   910 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:04 · PVG 04:04 · LAX 13:04 · JFK 16:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.