本文记录了 Ubuntu 和 HDF5 版本不匹配所导致的问题和解决方法。

Ubantu 中配置 HDF5,在大部分情况下只需运行下面指令即可完成。

sudo apt-get update
sudo apt-get install libhdf5-dev
sudo apt-get install libhdf5-serial-dev

  但是当 Ubantu 的版本和 HDF5 版本不匹配的时候,虽然运行上面指令,任然可以完成安装,但是当某些程序调用时,就会出现各种稀奇古怪的报错,这些报错几乎在 google 上搜不到,扰乱解决报错的方向。它们之间的版本对应关系可以参考下面网址。
HDF5 vulnerabilities: https://ubuntu.com/security/notices/USN-5272-1

Ubantu HDF5
20.04 1.10.4
18.04 1.10.0
16.04 1.8.16
14.04 1.8.11

1 手动对 HDF5 进行版本降级

  本次是在 Ubuntu 18.04.6 上发现报错的,其中 HDF5 版本为 1.10.4,所以需要把 HDF5 降级为 1.10.0。由于 apt-get 并不能像 pip 一样,可以在安装的时候指定所需版本,所以需要先把之前的卸载干净后,再本地安装 1.10.0 版本的 HDF5 即可,具体操作参考下面代码。

## 1 卸载 HDF5
sudo apt-get remove libhdf5-dev
sudo apt-get remove libhdf5-serial-dev
# HDF5 1.10.4 对应的是 libhdf5-103,根据实际情况灵活变动
sudo apt-get remove libhdf5-103 
# 有时运行上面代码,卸载失败或卸载完后,会提示运行下面代码,需要运行之后,再继续失败或下一步指令
sudo apt --fix-broken install
sudo apt-get autoremove

  卸载干净与否可以在运行 ls /usr/lib/x86_64-linux-gnu/ | grep libhdf5_serial 后,查看是否有输出来判断,如果没有任何输出则表示卸载干净,如果有下面输出则表示还需要卸载。

libhdf5_serial.a
libhdf5_serial_fortran.a
libhdf5_serial_fortran.so -> libhdf5_serial_fortran.so.100.1.2
libhdf5_serial_fortran.so.100 -> libhdf5_serial_fortran.so.100.1.2
libhdf5_serial_fortran.so.100.1.2
libhdf5_serial_hl.a
libhdf5_serialhl_fortran.a
libhdf5_serialhl_fortran.so -> libhdf5_serialhl_fortran.so.100.0.3
libhdf5_serialhl_fortran.so.100 -> libhdf5_serialhl_fortran.so.100.0.3
libhdf5_serialhl_fortran.so.100.0.3
libhdf5_serial_hl.so -> libhdf5_serial_hl.so.100.1.1
libhdf5_serial_hl.so.100 -> libhdf5_serial_hl.so.100.1.1
libhdf5_serial_hl.so.100.1.1
libhdf5_serial.settings
libhdf5_serial.so -> libhdf5_serial.so.103.0.0
libhdf5_serial.so.103 -> libhdf5_serial.so.103.0.0
libhdf5_serial.so.103.0.0

Tips:

  1. 考资料1中提到,可以运行 sudo ln -s /usr/lib/x86_64-linux-gnu/libhdf5_serial.so.103 /usr/lib/x86_64-linux-gnu/libhdf5_serial.so.100,从而手动创建一个实际为 libhdf5_serial.so.103libhdf5_serial.so.100 的软连接,来消除 libhdf5_serial.so.100 无法找到的报错,但是还会有新的更加奇怪的报错出现。不过有的缺少库的报错是因为安装位置的原因,完全可以使用这种设置软连接的方式解决。
  2. libhdf5_serial.so.103 的路径并不一定和本文记录的一致,可以通过运行 sudo find / -type f -name "libhdf5_hl.so*" 来确定。
  3. 一定要看完运行输出的文字,根据提示灵活变动。

  把之前的 HDF5 完全清理后,就需要手动本地安装对应版本的 HDF5,本次是下载 deb 文件进行安装,下载链接如下,因为存在依赖关系,所以需要依次运行下面代码。
hdf5 package in Ubuntu: https://launchpad.net/ubuntu/+source/hdf5

## 2 本地安装 HDF5
sudo dpkg -i ./hdf5-helpers_1.10.0-patch1+docs-4_amd64.deb
sudo dpkg -i ./libhdf5-100_1.10.0-patch1+docs-4_amd64.deb
sudo dpkg -i ./libhdf5-cpp-100_1.10.0-patch1+docs-4_amd64.deb
sudo apt-get install libaec-dev
sudo dpkg -i ./libhdf5-dev_1.10.0-patch1+docs-4_amd64.deb

Tips:

  1. 不同版本的 deb 文件的中间代号是不一致的,所以使用开头名称和版本(如: hdf5-helpers_1.10.0)进行搜索来精确定位,其中本次的服务器需要 amd64 构架,根据实际情况改动。
  2. 第2行代码在运行时出现 libhdf5-103:amd64 conflicts with libhdf5-100 的报错,就是没有卸载干净,运行对应卸载部分的代码即可。
  3. 一定要看完运行输出的文字,根据提示灵活变动。

2 如何确定是版本不匹配造成的 !!!

  怎么确定是版本不匹配造成的,这是个非常好的问题 !!!
  最初是在 R 中加载 (或安装) hdf5r 时,出现 libhdf5_serial.so.100 无法找到的报错,使用第一部分中的代码确实找不到,只能找到 libhdf5_serial.so.103 ,我的固有思想是觉得 R 包的版本有问题有问题,当然换不同版本的 R 包安装也是最简单的一步。
  当我在安装了不同版本的 R 包,均出现相同报错的时候,我就觉得可能不是这个原因,应该是 Ubantu 中的 HDF5 有问题,首当其冲的就运行了,本文开头的那三行指令,代码运行起来没有任何报错,一副岁月安好的样子,但是一装 hdf5r ,依旧是熟悉的报错,这时候才开始自己思考报错的含义,并且又搜索大量的相关信息。
  随后就进入到,既然可以找到 libhdf5_serial.so.103,那就软连接创建一个 libhdf5_serial.so.100 来解决,找不到的报错,但是后面在安装的时候又出现了下面一些报错,这个报错搜不到相关的网页,是一条死胡同。

## error 1:报错整体没有记录,报错中主要是包含下面字符

SZ_encoder_enabled

## error 2

Error: package or namespace load failed for ‘hdf5r’ in dyn.load(file, DLLpath = DLLpath, ...): unable to load shared object '/data1/yangpp/R_library/4.1/hdf5r/libs/hdf5r.so': /data1/yangpp/R_library/4.1/hdf5r/libs/hdf5r.so: undefined symbol: H5Oget_info_by_name, version HDF5_SERIAL_1.8.7

  所以还是回到 libhdf5_serial.so.100 不存在的问题上,100是小于103的,那就可以想到是当前的 HDF5 版本过高导致没得这个文件。后面就向着这个方向上努力,才有了能够解决此次报错的方法。


参考资料:
1.Ubuntu 20.04 - libhdf5_serial.so.10 not found (Gdal installation)