現有的 .so 文件即使存在也無法載入,似乎取決於 Docker 主機作業系統
我在基於 Alma8 的 Docker 容器中建構了 Qt6,Docker 主機是 Fedora 35。
在某些情況下(如下所述),所有 Qt 庫都無法載入
libQt6Core.so[.6[.2.4]]
. 但是該文件存在並且在正確的目錄中搜尋該文件。libQt6Dbus.so
找到並載入其他 Qt 庫(例如)。廣泛的調試、重建、搜尋網路並沒有產生任何線索,根本原因是什麼以及我如何解決它。
定位問題
我已將問題縮小到以下情況:
- 我創建了兩個最小的虛擬機,一個使用 centos7,一個使用 alma8。
- 我從官方倉庫安裝了 Docker 到他們兩個中。
- 我在兩個 VM 中執行了相同的 Docker 映像並安裝了相同的 qt6 包。
- 當 Docker 主機是 centos7 時它會中斷。
- 它在 Docker 主機為 alma8 時工作。
理論與問題
- Qt6 是在 Alma8 上建構的,並且連結到一些比 Centos7 提供的更新的系統庫,因此 Qt6 不能在 Centos7 下執行(這是完全可以預料的,也可以)。但它應該在 Alma8 Docker 容器中的任何位置執行。
- 容器鏡像應該能夠在任何地方執行,但在這種情況下,來自主機作業系統的“某些東西”會潛入容器並導致問題——即使兩個容器使用完全相同的鏡像!
問題是:這是什麼“東西”以及它如何/為什麼會破壞建構?
我試過的
我檢查
libQt6Gui.so
了它是否可以載入libQt6Core.so
,我檢查libQt6Core.so
了是否有東西看起來是假的:
ldd
並且LD_DEBUG=libs ldd
確實顯示出一些差異(見下文)- libtree沒有顯示出任何差異(但是一棵很好的樹:))
- pyldd(來自 conda-build)
readelf -d
我也嘗試過:
- 設置
LD_LIBRARY_PATH
(沒有改變任何東西——這並不奇怪,因為我知道總是搜尋正確的路徑)- 在帶有 centos7 主機的 alma8 容器中建構 Qt6(建構失敗並顯示“
libQt6Core.so.6
:無法打開文件”,與建構的庫相同的錯誤)- 在 centos7 容器中建構 Qt6(由於我還無法修復的其他問題,建構失敗)
區別於
ldd
在下面的螢幕截圖中,您可以看到左側Centos7 主機上的 Alma8-Docker-Container 和 *右側 Alma8 主機上的 Alma8-Docker-Container。
前兩張圖片顯示了
ldd /opt/emsconda/lib/libQt6Gui.so
.libQt6Core
在左邊找不到,但在右邊找到。第二個螢幕截圖顯示找到並載入了其他 Qt庫。左側的 ICU 庫也失去了——也許它們只在 libQt6Core 也被載入時才被載入?
此螢幕截圖顯示了
LD_DEBUG=libs ldd ...
. 您可以看到,在這兩種情況下,libQt6Core
都是在正確的位置搜尋 (/opt/emsconda/lib
)。但它只裝載在正確的容器中。左邊的另外一個在 `/opt/emsconda/lib/./ (haha)) 中查找,然後默默地走到下一個 lib …我找不到任何錯誤消息。這個文件只是沒有打開/載入。
檢查它
libQt6Core.so
本身可能會給我們一個線索。它連結到一個linux-vdso.so.1
.根據這個 SO question,該文件是作業系統核心注入使用者空間的虛擬庫。
由於 Docker 容器不執行自己的核心,我懷疑該文件來自主機作業系統。也許,
libQt6Core
依賴於linux-vdso.so.1
centos7核心無法提供的某些功能?我不知道 …由於到目前為止我沒有嘗試過產生錯誤消息,因此我不知道實際問題可能是什麼或如何進行調試。對於任何類型的提示、提示或幫助,我將不勝感激。
這個問題在 Qt 論壇中得到了答案。
概括:
.so
包含一個 ABI 標記,表示所需的最低核心版本。您可以通過objdump -s -j .note.ABI-tag libQt6Core.so.6.2.4
. 結果在最後三個塊中(在我的例子中是0x03
0x11
0x00
->3.17.0
)。- 由於 QT 使用了一些僅適用於較新核心的系統呼叫,因此此資訊是故意放置在那裡的。
- Glibc 在載入共享對象時讀取此資訊並將其與目前核心的版本進行比較。如果不匹配,則不會載入文件。
- 由於 Docker 沒有自己的核心,因此使用 Docker 主機的核心版本進行比較。因此,即使 Docker 鏡像是 Alma8,在我的例子中,核心仍然是來自 Centos7 主機的舊 v3.10.0。
- 您可以使用
strip --remove-section=.note.ABI-tag libQt6Core.so.6.2.4
. Qt 似乎有備份程式碼,所以沒有任何問題。