
我剛剛下載了一個tar
文件,該文件應該包含運行我們可以調用的程式所需的所有內容some_binary
。我提取了它的內容,我看到以下內容:
- 一個二進位(我們稱之為
some_binary
) - 包含各種動態庫(.so 檔案)的資料夾
lib
,例如/lib/ld-linux-x86-64.so
- 和一個名為的 shell 腳本
some_binary.sh
該腳本有以下內容:
#!/bin/bash
`dirname "$0"`/lib/ld-linux-x86-64.so.2 `dirname "$0"`/some_binary "$@"
並運行它似乎./some_binary.sh some arguments
運行./some_binary
正確。奇怪的是,運行以下腳本:
#!/bin/bash
LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
./some_binary "$@"
因為./my_script.sh some arguments
不起作用。它會導致重定位錯誤(未定義的符號),可能是由於錯誤地加載了下面的庫./lib
此外,從命令列運行以下兩個語句會導致segmentation fault
:
> LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
> ./some_binary some arguments
有了這個,我的問題是:
- 第一個腳本的作用是什麼?
- 為什麼我在這三種嘗試中都會得到不同的結果?為什麼我不能直接添加
$pwd/lib
然後LD_LIBRARY_PATH
運行some_binary
?
答案1
該程式帶有自己的動態載入器。程式很少需要自己的動態載入器:通常您系統上的動態載入器也可以運作。如果程式連結到 GNU libc 之外的標準函式庫,或連結到使用奇怪設定編譯的 GNU libc,則這可能是必要的。
告訴載入程式在哪裡可以找到程式的首選庫就足夠了。你的嘗試幾乎做到了這一點,但不完全是。如果LD_LIBRARY_PATH
尚未在環境中,則賦值LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
僅定義 shell 變量,而不是環境變量,因此程式看不到任何東西。此外,$CWD
通常會擴展為空字串,您可能指的是$PWD
或更好$(dirname "$0")
(即包含腳本的目錄)。另請注意,您在問題中使用了lib
和不一致的內容。LIB
嘗試
#!/bin/sh
export LD_LIBRARY_PATH="$(dirname "$0")/lib:$LD_LIBRARY_PATH"
exec "$(dirname "$0")/some_binary" "$@"
或者更好的是,如果之前沒有定義,則避免在末尾有一個空條目LD_LIBRARY_PATH
(這可能很糟糕,因為空條目代表當前目錄,但在路徑末尾,只有在庫不存在時才有害的)沒有找到它應該在的地方):
#!/bin/sh
export LD_LIBRARY_PATH="$(dirname "$0")/lib:$LD_LIBRARY_PATH"
case "$LD_LIBRARY_PATH" in *:) LD_LIBRARY_PATH=${LD_LIBRARY_PATH%:};; esac
exec "$(dirname "$0")/some_binary" "$@"