AttributeError: /lib/x86_64-linux-gnu/libbcc.so.0: undefined symbol: bpf_module_create_b

AttributeError: /lib/x86_64-linux-gnu/libbcc.so.0: undefined symbol: bpf_module_create_b

背景

在Ubuntu22的虚拟机中,使用源码编译并安装好bcc工具库后,执行bcc工具python3 /usr/share/bcc/tools/execsnoop报错。

报错信息

报错信息如下:

root@ubuntu2204vm:/usr/share/bcc/tools# ./execsnoop
Traceback (most recent call last):
  File "/usr/share/bcc/tools/./execsnoop", line 23, in <module>
    from bcc import BPF
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 27, in <module>
    from .libbcc import lib, bcc_symbol, bcc_symbol_option, bcc_stacktrace_build_id, _SYM_CB_TYPE
  File "/usr/lib/python3/dist-packages/bcc/libbcc.py", line 20, in <module>
    lib.bpf_module_create_b.restype = ct.c_void_p
    ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/ctypes/__init__.py", line 389, in __getattr__
    func = self.__getitem__(name)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/ctypes/__init__.py", line 394, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: /lib/x86_64-linux-gnu/libbcc.so.0: undefined symbol: bpf_module_create_b

解决方法

网上的目前的解决办法

主要还是python版本问题,将python2切换为python3。而我这边显然不是这个问题,因为我的机子上只有python3

复制已编译的bcc库中的python bcc库到python3的库中

cp -r /root/ebpf/bcc/build/src/python/bcc-python3/bcc/* /usr/lib/python3/dist-packages/bcc/

错误分析过程

报错的相关路径

根据报错信息,和报错相关的路径:
/lib/x86_64-linux-gnu/libbcc.so.0: bcc库采用的libbcc.so.0
/usr/lib/python3/dist-packages/bcc: 报错的bcc库

python版本检测

使用的均为python3,没有python2,所以不存在版本问题

# update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                 Priority   Status
------------------------------------------------------------
* 0            /usr/bin/python3.11   2         auto mode
  1            /usr/bin/python3.10   1         manual mode
  2            /usr/bin/python3.11   2         manual mode

libbcc库检查

# ls -lh /lib/x86_64-linux-gnu/ |grep libbcc
-rw-r--r--  1 root root  5.0M May  1 19:34 libbcc.a
-rw-r--r--  1 root root  1.5M May  1 19:33 libbcc_bpf.a
lrwxrwxrwx  1 root root    15 Jan 18  2021 libbcc_bpf.so -> libbcc_bpf.so.0
lrwxrwxrwx  1 root root    20 May  1 19:35 libbcc_bpf.so.0 -> libbcc_bpf.so.0.27.0
-rw-r--r--  1 root root   51K Jan 18  2021 libbcc_bpf.so.0.18.0
-rw-r--r--  1 root root  2.8M May  1 19:33 libbcc_bpf.so.0.27.0
-rw-r--r--  1 root root  243K May  1 19:33 libbcc-loader-static.a
lrwxrwxrwx  1 root root    11 Jan 18  2021 libbcc.so -> libbcc.so.0
lrwxrwxrwx  1 root root    16 May  1 19:35 libbcc.so.0 -> libbcc.so.0.27.0
-rw-r--r--  1 root root  3.3M Jan 18  2021 libbcc.so.0.18.0
-rw-r--r--  1 root root  105M May  1 19:34 libbcc.so.0.27.0

可以看到libbcc库的实际指向为:
libbcc.so.0 -> libbcc.so.0.27.0

根据报错内容,python库需要bpf_module_create_b,而libbcc.so.0.27.0中没有
可以通过以下命令查看:

# strings /lib/x86_64-linux-gnu/libbcc.so.0.27.0 |grep bpf_module_create_
bpf_module_create_c
bpf_module_create_c_from_string
bpf_module_create_c.cold
bpf_module_create_c_from_string.cold
bpf_module_create_c
bpf_module_create_c_from_string

此时注意到上一个步骤中的libbcc.so.0.18.0,同样进行bpf_module_create_b检查

# strings /lib/x86_64-linux-gnu/libbcc.so.0.18.0 |grep bpf_module_create_
bpf_module_create_b
bpf_module_create_c
bpf_module_create_c_from_string

发现存在bpf_module_create_b,即便不进行时间对比,通过版本号0.18.0与0.27.0也知道,
python3的bcc库竟然请求的是老版(0.18.0)的bcc lib库

python3 bcc库检查

# ll  /usr/lib/python3/dist-packages/bcc/
total 212
drwxr-xr-x   3 root root  4096 May  2 00:13 ./
drwxr-xr-x 156 root root 12288 May  1 19:36 ../
-rw-r--r--   1 root root  2566 Jan 18  2021 containers.py
-rw-r--r--   1 root root 20914 Jan 18  2021 disassembler.py
-rw-r--r--   1 root root 58581 Jan 18  2021 __init__.py
-rw-r--r--   1 root root 12951 Jan 18  2021 libbcc.py
-rw-r--r--   1 root root  4693 Jan 18  2021 perf.py
drwxr-xr-x   2 root root  4096 May  1 19:37 __pycache__/
-rw-r--r--   1 root root  9656 Jan 18  2021 syscall.py
-rw-r--r--   1 root root 40588 Jan 18  2021 table.py
-rw-r--r--   1 root root  1604 Jan 18  2021 tcp.py
-rw-r--r--   1 root root  9102 Jan 18  2021 usdt.py
-rw-r--r--   1 root root  4904 Jan 18  2021 utils.py
-rw-r--r--   1 root root    23 Jan 18  2021 version.py

根据文件时间可以确定,确实都是21年的老库,遂进行替换,先查找bcc源码中的bcc python库:

# find / -name libbcc.py -ls 2>/dev/null
  2360806  16 ... 12951 Jan 18  2021 /usr/lib/python3/dist-packages/bcc/libbcc.py
  1054215  16 ... 14561 May  1 19:32 /root/ebpf/bcc/build/src/python/bcc-python3/build/lib/bcc/libbcc.py
  1053905  16 ... 14561 May  1 19:32 /root/ebpf/bcc/build/src/python/bcc-python3/bcc/libbcc.py
  1052874  16 ... 14561 May  1 19:31 /root/ebpf/bcc/src/python/bcc/libbcc.py 

因为笔者对python并不算熟悉,不知道如何进行正确替换,所以直接进行的复制
cp -r /root/ebpf/bcc/build/src/python/bcc-python3/bcc/* /usr/lib/python3/dist-packages/bcc/

替换后再次执行bcc命令,问题成功得到解决,效果如下:

# ./execsnoop
PCOMM            PID     PPID    RET ARGS
sshd             7924    909       0 /usr/sbin/sshd -D -R
00-header        7928    7927      0 /etc/update-motd.d/00-header
uname            7929    7928      0 /usr/bin/uname -o
uname            7930    7928      0 /usr/bin/uname -r
uname            7931    7928      0 /usr/bin/uname -m
### 解决方案概述 当遇到 `ImportError: GLIBCXX_3.4.29 not found` 的错误时,这通常是因为系统的 GCC 版本过旧,导致缺少所需的 C++ 标准库版本。此问题可能会影响多个依赖项的加载,包括像 `sklearn` 这样的机器学习库。 以下是针对该问题的具体分析和解决方案: --- #### 1. **确认当前系统中的 GCC 和 glibcxx 版本** 可以通过以下命令检查当前安装的 GCC 及其对应的 `libstdc++.so` 文件版本: ```bash strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX ``` 如果输出中不包含 `GLIBCXX_3.4.29` 或更高版本,则说明需要升级 GCC[^1]。 --- #### 2. **更新 GCC 到支持所需标准库的版本** 对于 Linux 系统,可以尝试通过包管理器或源码编译来更新 GCC。例如,在基于 Debian 的发行版上运行以下命令: ```bash sudo apt update && sudo apt install gcc-10 g++-10 ``` 设置默认使用的 GCC 版本: ```bash sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100 ``` 验证新版本是否生效: ```bash gcc --version g++ --version ``` 重新构建 `libstdc++` 后再次执行上述字符串匹配命令以确认已解决问题。 --- #### 3. **创建软链接到兼容的标准库文件** 如果无法全局更新 GCC,可以选择手动下载并配置新的 `libstdc++.so` 文件作为替代方法。具体操作如下: 从官方 GNU 官方网站或其他可信资源获取最新版本的 GCC 并提取其中的共享对象文件: ```bash wget http://ftp.gnu.org/gnu/gcc/gcc-10.3.0/gcc-10.3.0.tar.gz tar -xf gcc-10.3.0.tar.gz cd gcc-10.3.0 find . -name "libstdc++.so*" cp ./path/to/new/libstdc++.so.6 ~/custom_lib/ export LD_LIBRARY_PATH=~/custom_lib:$LD_LIBRARY_PATH ``` 这样会强制程序优先使用指定路径下的动态链接库而非系统自带的老版本。 --- #### 4. **在 Miniconda 中单独处理环境冲突** 由于问题是发生在 Miniconda 下,因此建议为项目创建独立虚拟环境,并确保所有必要的依赖都来自 Conda 渠道而不是 PyPI。例如: ```bash conda create -n sklearn_env python=3.8 conda activate sklearn_env conda install scikit-learn numpy pandas matplotlib ``` 这种方式能够有效规避因不同工具链间差异引发的一系列潜在隐患。 --- #### 5. **其他注意事项** 有时即使解决了本地开发机上的问题,部署至生产服务器仍可能出现类似状况。为此推荐始终打包应用程序及其全部依赖(如通过 Docker 镜像),从而实现完全一致的运行条件控制[^2]。 --- ### 示例代码片段 下面展示如何测试当前环境中是否存在目标符号定义以及切换默认GCC版本的过程: ```python import ctypes try: ctypes.CDLL('libstdc++.so.6').GLIBCXX_3_4_29 except AttributeError as e: print(f"Missing symbol: {e}") else: print("Symbol exists.") ``` ---
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值