
Я только что скачал tar
файл, который должен включать все необходимое для запуска программы, которую мы можем назвать some_binary
. Я извлек его содержимое и вижу следующее:
- Двоичный файл (назовем его так
some_binary
) - Папка
lib
с различными динамическими библиотеками (файлы .so), такими как/lib/ld-linux-x86-64.so
- и скрипт оболочки под названием
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 "$@"
as ./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
определяет только переменную оболочки, а не переменную среды, поэтому программа ничего не видит. Более того, $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" "$@"