Несколько библиотек glibc на одном хосте
Несколько библиотек glibc на одном хосте
Мой сервер Linux (SLES-8) в настоящее время имеет glibc-2.2.5-235, но у меня есть программа, которая не будет работать в этой версии и требует glibc-2.3.3.
Можно ли установить несколько glibcs на одном хосте?
Это ошибка, которую я получаю, когда запускаю свою программу на старом glibc:
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./myapp)
./myapp: /lib/i686/libpthread.so.0: version `GLIBC_2.3.2' not found (required by ./myapp)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libxerces-c.so.27)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
Поэтому я создал новый каталог с именем newglibc и скопировал следующие файлы:
libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so
а также
export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH
Но я получаю ошибку:
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libpthread.so.0)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by libstdc++.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libm.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./newglibc/libc.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libc.so.6)
Таким образом, кажется, что они все еще ссылаются на /lib и не поднимают, откуда я их положил?
Спасибо
10 ответов
Очень возможно иметь несколько версий glibc в одной системе (мы делаем это каждый день).
Однако вы должны знать, что glibc состоит из множества частей (более 200 общих библиотек), которые должны соответствовать всем. Одним из компонентов является ld-linux.so.2, и он должен соответствовать libc.so.6, иначе вы увидите ошибки, которые видите.
Абсолютный путь к ld-linux.so.2 жестко запрограммирован в исполняемый файл во время соединения и не может быть легко изменен после того, как соединение выполнено.
Чтобы создать исполняемый файл, который будет работать с новым glibc, сделайте следующее:
g++ main.o -o myapp ... \
-Wl,--rpath=/path/to/newglibc \
-Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2
-rpath
опция компоновщика заставит загрузчик среды выполнения искать библиотеки в /path/to/newglibc
(чтобы вам не пришлось устанавливать LD_LIBRARY_PATH
перед запуском), а -dynamic-linker
опция будет "печь" путь для исправления ld-linux.so.2
в приложение.
Если вы не можете связать myapp
приложение (например, потому что это сторонний бинарный файл), не все потеряно, но становится сложнее. Одним из решений является установка правильного chroot
среда для этого. Другая возможность - использовать rtldi и бинарный редактор.
Этот вопрос старый, остальные ответы старые. Ответ "Занятого русского" очень хороший и информативный, но он работает только при наличии исходного кода. Если нет, альтернативы тогда были очень хитрыми. К счастью, в настоящее время у нас есть простое решение этой проблемы (как прокомментировано в одном из его ответов) с использованием patchelf. Все, что вам нужно сделать, это:
$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp
И после этого вы можете просто выполнить свой файл:
$ ./myapp
Не нужно chroot
или вручную редактировать двоичные файлы, к счастью. Но не забудьте сделать резервную копию вашего бинарного файла перед его исправлением, если вы не уверены, что делаете, потому что он изменяет ваш бинарный файл. После того, как вы исправите его, вы не сможете восстановить старый путь к интерпретатору /rpath. Если это не сработает, вам придется исправлять его до тех пор, пока вы не найдете путь, который на самом деле будет работать... Ну, это не должен быть процесс проб и ошибок. Например, в примере с ОП ему понадобилось GLIBC_2.3
, так что вы можете легко найти, какая библиотека предоставляет эту версию, используя strings
:
$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3
Теоретически, первый grep будет пустым, потому что системный libc не имеет нужной версии, а второй должен вывести GLIBC_2.3, потому что он имеет версию myapp
использует, поэтому мы знаем, что можем patchelf
наш двоичный файл, используя этот путь.
Когда вы пытаетесь запустить двоичный файл в Linux, двоичный файл пытается загрузить компоновщик, а затем библиотеки, и все они должны быть в пути и / или в нужном месте. Если ваша проблема связана с компоновщиком, и вы хотите узнать, какой путь ищет ваш двоичный файл, вы можете узнать с помощью этой команды:
$ readelf -l myapp | grep interpreter
[Requesting program interpreter: /lib/ld-linux.so.2]
Если ваша проблема с библиотеками, команды, которые дадут вам используемые библиотеки:
$ readelf -d myapp | grep Shared
$ ldd myapp
Это перечислит библиотеки, которые нужны вашему бинарному файлу, но вы, вероятно, уже знаете проблемные, поскольку они уже дают ошибки, как в случае с OP.
"patchelf" работает для многих различных проблем, с которыми вы можете столкнуться при попытке запустить программу, связанных с этими двумя проблемами. Например, если вы получаете: ELF file OS ABI invalid
, это можно исправить установкой нового загрузчика (--set-interpreter
часть команды), как я объясню здесь. Другой пример - проблема получения No such file or directory
когда вы запускаете файл, который там и исполняемый, как показано здесь. В этом конкретном случае у OP отсутствовала ссылка на загрузчик, но, возможно, в вашем случае у вас нет root-доступа и вы не можете создать ссылку. Установка нового переводчика решит вашу проблему.
Спасибо Employed Russian и Михаилу Панкову за понимание и решение!
Используйте LD_PRELOAD: поместите вашу библиотеку где-нибудь в каталогах man lib и запустите:
LD_PRELOAD='mylibc.so anotherlib.so' program
Смотрите: статья в Википедии
Прежде всего, наиболее важной зависимостью каждой динамически связанной программы является компоновщик. Все так библиотеки должны соответствовать версии компоновщика.
Давайте рассмотрим простой пример: у меня есть система Ubuntu newset, в которой я запускаю какую-то программу (в моем случае это D-компилятор - ldc2). Я хотел бы запустить его на старом CentOS, но из-за старой библиотеки glibc это невозможно. я получил
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
Я должен скопировать все зависимости из Ubuntu в Centos. Правильный метод заключается в следующем:
Сначала давайте проверим все зависимости:
ldd ldc2-1.5.0-linux-x86_64/bin/ldc2
linux-vdso.so.1 => (0x00007ffebad3f000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f965f597000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f965f378000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f965f15b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f965ef57000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965ec01000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f965e9ea000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f965e60a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f965f79f000)
linux-vdso.so.1 не является настоящей библиотекой, и нам не нужно об этом заботиться.
/lib64/ld-linux-x86-64.so.2 - это компоновщик, который используется linux для связи исполняемого файла со всеми динамическими библиотеками.
Остальные файлы являются настоящими библиотеками, и все они вместе с компоновщиком должны быть скопированы где-то в centos.
Предположим, что все библиотеки и компоновщик находятся в каталоге "/mylibs".
ld-linux-x86-64.so.2 - как я уже сказал - это компоновщик. Это не динамическая библиотека, а статический исполняемый файл. Вы можете запустить его и увидеть, что у него даже есть некоторые параметры, например --library-path (я вернусь к нему).
В Linux динамически связанная программа может запускаться только по имени, например
/bin/ldc2
Linux загружает такую программу в ОЗУ и проверяет, какой компоновщик для нее установлен. Обычно в 64-битной системе это /lib64/ld-linux-x86-64.so.2 (в вашей файловой системе это символическая ссылка на реальный исполняемый файл). Затем linux запускает компоновщик и загружает динамические библиотеки.
Вы также можете немного изменить это и сделать такой трюк:
/mylibs/ld-linux-x86-64.so.2 /bin/ldc2
Это метод принуждения linux к использованию определенного компоновщика.
И теперь мы можем вернуться к упомянутому ранее параметру --library-path
/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2
Он запустит ldc2 и загрузит динамические библиотеки из /mylibs.
Это метод для вызова исполняемого файла с выбранными (не системными) библиотеками.
Настройка 1: скомпилируйте свой собственный glibc без выделенного GCC и используйте его
Эта настройка может работать и быстро, так как не перекомпилирует весь набор инструментов GCC, только glibc.
Но это ненадежно, так как использует объекты среды выполнения C, такие как crt1.o
, crti.o
, а также crtn.o
предоставлено glibc. Об этом упоминается по адресу: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21. Эти объекты выполняют раннюю настройку, на которую опирается glibc, поэтому я не удивлюсь, если что-нибудь не получится и удивительно тонкие способы.
Для более надежной настройки см. Настройка 2 ниже.
Соберите glibc и установите локально:
export glibc_install="$(pwd)/glibc/build/install"
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`
Настройка 1: проверить сборку
test_glibc.c
#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>
atomic_int acnt;
int cnt;
int f(void* thr_data) {
for(int n = 0; n < 1000; ++n) {
++cnt;
++acnt;
}
return 0;
}
int main(int argc, char **argv) {
/* Basic library version check. */
printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());
/* Exercise thrd_create from -pthread,
* which is not present in glibc 2.27 in Ubuntu 18.04.
* https://stackru.com/questions/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
thrd_t thr[10];
for(int n = 0; n < 10; ++n)
thrd_create(&thr[n], f, NULL);
for(int n = 0; n < 10; ++n)
thrd_join(thr[n], NULL);
printf("The atomic counter is %u\n", acnt);
printf("The non-atomic counter is %u\n", cnt);
}
Скомпилируйте и запустите test_glibc.sh
:
#!/usr/bin/env bash
set -eux
gcc \
-L "${glibc_install}/lib" \
-I "${glibc_install}/include" \
-Wl,--rpath="${glibc_install}/lib" \
-Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
-std=c11 \
-o test_glibc.out \
-v \
test_glibc.c \
-pthread \
;
ldd ./test_glibc.out
./test_glibc.out
Программа выводит ожидаемое:
gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674
Команда адаптирована из https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21, но --sysroot
сделал это с помощью:
cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install
так что я его убрал.
ldd
вывод подтверждает, что ldd
и библиотеки, которые мы только что создали, фактически используются как ожидалось:
+ ldd test_glibc.out
linux-vdso.so.1 (0x00007ffe4bfd3000)
libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
/home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)
gcc
выходные данные отладки компиляции показывают, что использовались мои объекты среды выполнения хоста, что плохо, как упоминалось ранее, но я не знаю, как обойти это, например, оно содержит:
COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o
Настройка 1: изменить glibc
Теперь давайте изменим glibc:
diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <stdio.h>
+
#include "thrd_priv.h"
int
thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
{
+ puts("hacked");
_Static_assert (sizeof (thr) == sizeof (pthread_t),
"sizeof (thr) != sizeof (pthread_t)");
Затем перекомпилируйте и переустановите glibc, перекомпилируйте и перезапустите нашу программу:
cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh
и мы видим hacked
напечатано несколько раз, как и ожидалось.
Это еще раз подтверждает, что мы фактически использовали скомпилированный glibc, а не хост.
Проверено на Ubuntu 18.04.
Настройка 2: первоначальная настройка crosstool-NG
Это альтернатива настройке 1, и это наиболее правильная установка, которую я достиг до сих пор: насколько я могу наблюдать, все правильно, включая объекты времени выполнения C, такие как crt1.o
, crti.o
, а также crtn.o
,
В этой настройке мы скомпилируем полный выделенный набор инструментов GCC, который использует желаемый glibc.
Единственным недостатком этого метода является то, что сборка займет больше времени. Но я бы не стал рисковать производственной установкой с чем-то меньшим.
crosstool-NG - это набор скриптов, который загружает и компилирует для нас все из исходного кода, включая GCC, glibc и binutils.
Да, система сборки GCC настолько плоха, что нам нужен отдельный проект для этого.
Эта настройка не идеальна, потому что crosstool-NG не поддерживает сборку исполняемых файлов без дополнительных -Wl
flags, что кажется странным с тех пор, как мы создали GCC. Но все, кажется, работает, так что это только неудобство.
Получите crosstool-NG и настройте его:
git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout a6580b8e8b55345a5a342b5bd96e42c83e640ac5
export CT_PREFIX="$(pwd)/.build/install"
export PATH="/usr/lib/ccache:${PATH}"
./bootstrap
./configure --enable-local
make -j `nproc`
./ct-ng x86_64-unknown-linux-gnu
./ct-ng menuconfig
Единственный обязательный параметр, который я вижу, - это соответствие версии ядра вашего хоста для использования правильных заголовков ядра. Найдите версию ядра своего хоста с помощью:
uname -a
который показывает мне:
4.15.0-34-generic
так в menuconfig
Я делаю:
Operating System
Version of linux
поэтому я выбираю:
4.14.71
которая является первой равной или более старой версией. Он должен быть старше, поскольку ядро обратно совместимо.
Теперь вы можете построить с:
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`
и теперь подождите от тридцати минут до двух часов для компиляции.
Настройка 2: дополнительные конфигурации
.config
что мы создали с ./ct-ng x86_64-unknown-linux-gnu
имеет:
CT_GLIBC_V_2_27=y
Чтобы изменить это, в menuconfig
делать:
C-library
Version of glibc
спасти .config
и продолжить сборку.
Или, если вы хотите использовать свой собственный исходный код glibc, например, чтобы использовать glibc из последней версии git, выполните следующее:
Paths and misc options
Try features marked as EXPERIMENTAL
: установить в true
C-library
Source of glibc
Custom location
: скажи даCustom location
Custom source location
: указать каталог, содержащий ваш исходный код glibc
где glibc был клонирован как:
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
Настройка 2: проверить это
Как только вы соберете нужный набор инструментов, протестируйте его с помощью:
#!/usr/bin/env bash
set -eux
install_dir="${CT_PREFIX}/x86_64-unknown-linux-gnu"
PATH="${PATH}:${install_dir}/bin" \
x86_64-unknown-linux-gnu-gcc \
-Wl,--dynamic-linker="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2" \
-Wl,--rpath="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib" \
-v \
-o test_glibc.out \
test_glibc.c \
-pthread \
;
ldd test_glibc.out
./test_glibc.out
Кажется, все работает как в программе установки 1, за исключением того, что теперь использовались правильные объекты времени выполнения:
COLLECT_GCC_OPTIONS=/home/ciro/crosstool-ng/.build/install/x86_64-unknown-linux-gnu/bin/../x86_64-unknown-linux-gnu/sysroot/usr/lib/../lib64/crt1.o
Настройка 2: неудачная попытка перекомпиляции glibc
Это не представляется возможным с Crosstool-NG, как объяснено ниже.
Если вы просто перестроить;
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`
тогда ваши изменения в пользовательском расположении исходного кода glibc будут приняты во внимание, но он строит все с нуля, что делает его непригодным для итеративной разработки.
Если мы делаем:
./ct-ng list-steps
он дает хороший обзор шагов сборки:
Available build steps, in order:
- companion_tools_for_build
- companion_libs_for_build
- binutils_for_build
- companion_tools_for_host
- companion_libs_for_host
- binutils_for_host
- cc_core_pass_1
- kernel_headers
- libc_start_files
- cc_core_pass_2
- libc
- cc_for_build
- cc_for_host
- libc_post_cc
- companion_libs_for_target
- binutils_for_target
- debug
- test_suite
- finish
Use "<step>" as action to execute only that step.
Use "+<step>" as action to execute up to that step.
Use "<step>+" as action to execute from that step onward.
следовательно, мы видим, что есть этапы glibc, переплетенные с несколькими этапами GCC, в частности, libc_start_files
приходит раньше cc_core_pass_2
что, вероятно, самый дорогой шаг вместе с cc_core_pass_1
,
Чтобы построить только один шаг, вы должны сначала установить "Сохранить промежуточные шаги" в .config
Вариант для первоначальной сборки:
Paths and misc options
Debug crosstool-NG
Save intermediate steps
и тогда вы можете попробовать:
env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`
но, к сожалению, +
требуется, как указано на: https://github.com/crosstool-ng/crosstool-ng/issues/1033
Однако обратите внимание, что перезапуск с промежуточного шага сбрасывает каталог установки в состояние, в котором он находился на этом шаге. Т.е. у вас будет восстановленный libc - но окончательный компилятор не будет собран с этим libc (и, следовательно, нет библиотек компиляторов, таких как libstdC++).
и в основном все еще делает перестройку слишком медленной, чтобы ее можно было реализовать для разработки, и я не вижу, как преодолеть это, не исправляя crosstool-NG.
Кроме того, начиная с libc
шаг, кажется, не скопировать источник снова из Custom source location
, что делает этот метод непригодным для использования.
Бонус: stdlibC++
Бонус, если вы также заинтересованы в стандартной библиотеке C++: Как редактировать и перестраивать исходный код стандартной библиотеки GCC libstdC++ C++?
@msb дает безопасное решение.
Я встретил эту проблему, когда я сделал import tensorflow as tf
в среде Конда в CentOS 6.5
который имеет только glibc-2.12
,
ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/
Я хочу предоставить некоторые детали:
Первая установка glibc
в ваш домашний каталог:
mkdir ~/glibc-install; cd ~/glibc-install
wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
tar -zxvf glibc-2.17.tar.gz
cd glibc-2.17
mkdir build
cd build
../configure --prefix=/home/myself/opt/glibc-2.17 # <-- where you install new glibc
make -j<number of CPU Cores> # You can find your <number of CPU Cores> by using **nproc** command
make install
Во-вторых, следуйте тем же способом, чтобы установить patchelf;
В-третьих, исправьте ваш Python:
[myself@nfkd ~]$ patchelf --set-interpreter /home/myself/opt/glibc-2.17/lib/ld-linux-x86-64.so.2 --set-rpath /home/myself/opt/glibc-2.17/lib/ /home/myself/miniconda3/envs/tensorflow/bin/python
как упомянуто @msb
Теперь я могу использовать tensorflow-2.0 alpha
в CentOS 6.5
,
ссылка: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/
Можете ли вы рассмотреть возможность использования Nix http://nixos.org/nix/?
Nix поддерживает многопользовательское управление пакетами: несколько пользователей могут безопасно совместно использовать общее хранилище Nix, не нужно иметь привилегии root для установки программного обеспечения, а также могут устанавливать и использовать разные версии пакета.
Я не уверен, что вопрос по-прежнему актуален, но есть и другой способ решения проблемы: Docker. Можно установить практически пустой контейнер исходного дистрибутива (дистрибутив, используемый для разработки) и скопировать файлы в контейнер. Таким образом, вам не нужно создавать файловую систему, необходимую для chroot.
Когда я захотел запустить браузер chromium в Ubuntu (glibc-2.15), я получил (типичное) сообщение "...libc.so.6: версия`GLIBC_2.19'не найдена...". Я учел тот факт, что файлы нужны не постоянно, а только для запуска. Поэтому я собрал файлы, необходимые для браузера и sudo, и создал среду mini-glibc-2.19, запустил браузер и снова скопировал исходные файлы. Необходимые файлы находятся в оперативной памяти, и оригинальный glibc такой же.
as root
the files (*-2.15.so) already exist
mkdir -p /glibc-2.19/i386-linux-gnu
/glibc-2.19/ld-linux.so.2 -> /glibc-2.19/i386-linux-gnu/ld-2.19.so
/glibc-2.19/i386-linux-gnu/libc.so.6 -> libc-2.19.so
/glibc-2.19/i386-linux-gnu/libdl.so.2 -> libdl-2.19.so
/glibc-2.19/i386-linux-gnu/libpthread.so.0 -> libpthread-2.19.so
mkdir -p /glibc-2.15/i386-linux-gnu
/glibc-2.15/ld-linux.so.2 -> (/glibc-2.15/i386-linux-gnu/ld-2.15.so)
/glibc-2.15/i386-linux-gnu/libc.so.6 -> (libc-2.15.so)
/glibc-2.15/i386-linux-gnu/libdl.so.2 -> (libdl-2.15.so)
/glibc-2.15/i386-linux-gnu/libpthread.so.0 -> (libpthread-2.15.so)
скрипт для запуска браузера:
#!/bin/sh
sudo cp -r /glibc-2.19/* /lib
/path/to/the/browser &
sleep 1
sudo cp -r /glibc-2.15/* /lib
sudo rm -r /lib/i386-linux-gnu/*-2.19.so
Если вы внимательно посмотрите на второй вывод, вы увидите, что используется новое расположение для библиотек. Возможно, все еще отсутствуют библиотеки, которые являются частью glibc.
Я также считаю, что все библиотеки, используемые вашей программой, должны быть скомпилированы с этой версией glibc. Если у вас есть доступ к исходному коду программы, лучшим вариантом будет новая компиляция.
"Занятый русский" - один из лучших ответов, и я думаю, что все другие предложенные ответы могут не сработать. Причина в том, что когда приложение создается впервые, все необходимые ему API-интерфейсы разрешаются во время компиляции. Используя "ldd" вы можете увидеть все статически связанные зависимости:
ldd /usr/lib/firefox/firefox
linux-vdso.so.1 => (0x00007ffd5c5f0000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f727e708000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f727e500000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f727e1f8000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f727def0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f727db28000)
/lib64/ld-linux-x86-64.so.2 (0x00007f727eb78000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f727d910000)
Но во время выполнения Firefox также будет загружать много других динамических библиотек, например (для firefox) загружено много библиотек, помеченных "glib" (даже если статически связанных нет ни одной):
/usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2
/lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0
/usr/lib/x86_64-linux-gnu/libavahi-glib.so.1.0.2
Много раз, вы можете видеть, как названия одной версии мягко связаны с другой версией. Например:
lrwxrwxrwx 1 root root 23 Dec 21 2014 libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
-rw-r--r-- 1 root root 160832 Mar 1 2013 libdbus-glib-1.so.2.2.2
Следовательно, это означает, что в одной системе существуют разные версии "библиотек", что не является проблемой, поскольку это один и тот же файл, и это обеспечит совместимость, когда приложения имеют зависимости от нескольких версий.
Следовательно, на системном уровне все библиотеки практически взаимозависимы, и простое изменение приоритета загрузки библиотек с помощью манипуляции LD_PRELOAD или LD_LIBRARY_PATH не поможет - даже при загрузке во время выполнения все равно может произойти сбой.
http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc
Лучшая альтернатива - chroot (кратко упомянутое ER): но для этого вам нужно будет воссоздать всю среду, в которой выполняется исходное двоичное выполнение - обычно начиная с /lib, /usr/lib/, /usr/lib/x86 и т. Д. Вы можете использовать "Buildroot", или YoctoProject, или просто tar из существующей среды Distro. (как Fedora/Suse и т. д.).