Несколько библиотек 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 и не получают оттуда, где я их положил?
Спасибо
export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH
действительно решил проблему для меня! Это, конечно, не будет работать для всех, но это легко исправить, если это работает! Спасибо! :)Ответы:
Очень возможно иметь несколько версий glibc в одной системе (мы делаем это каждый день).
Однако вы должны знать, что glibc состоит из множества частей (более 200 общих библиотек), которые должны соответствовать всем. Одним из компонентов является ld-linux.so.2, и он должен соответствовать libc.so.6, иначе вы увидите ошибки, которые вы видите.
Абсолютный путь к ld-linux.so.2 жестко запрограммирован в исполняемый файл во время соединения и не может быть легко изменен после того, как соединение выполнено.
Чтобы создать исполняемый файл, который будет работать с новым glibc, сделайте следующее:
Опция
-rpath
компоновщика заставит загрузчик среды выполнения выполнять поиск библиотек/path/to/newglibc
(так что вам не нужно устанавливать егоLD_LIBRARY_PATH
перед запуском), а-dynamic-linker
опция «запечет» путь для исправленияld-linux.so.2
в приложении.Если вы не можете повторно связать
myapp
приложение (например, потому что это сторонний бинарный файл), не все потеряно, но становится сложнее. Одно из решений заключается в том, чтобы создать для этого подходящуюchroot
среду. Другая возможность - использовать rtldi и бинарный редактор .источник
-Wl,--dynamic-linker=file
(принимает два '-') работает только при компиляции для исполняемых файлов ELF. Проверка/sbin/ldconfig -p | grep ld
patchelf
( nixos.org/patchelf.html ), которая позволяет изменять rpath и интерпретатор уже скомпилированного ELF.-Wl,--rpath
а неLD_LIBRARY_PATH
может быть важным по причинам, не связанным с удобством: если программа запускает дочерние процессы, их значениеLD_LIBRARY_PATH
обычно наследуется, но если они также не скомпилированы для использования более новый glibc (например, если они как стоковые двоичные файлыbash
), они не будут запускаться./path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
-I
и-L
: stackoverflow.com/a/52454603/895245Этот вопрос старый, остальные ответы старые. Ответ «Занятого русского» очень хороший и информативный, но он работает только при наличии исходного кода. Если нет, то альтернативы тогда были очень хитрыми. К счастью, в настоящее время у нас есть простое решение этой проблемы (как прокомментировано в одном из его ответов) с использованием patchelf . Все, что вам нужно сделать, это:
И после этого вы можете просто выполнить свой файл:
К
chroot
счастью, нет необходимости или редактировать двоичные файлы вручную. Но не забудьте сделать резервную копию вашего двоичного файла перед его исправлением, если вы не уверены, что делаете, потому что он изменяет ваш двоичный файл. После того, как вы исправите его, вы не сможете восстановить старый путь к интерпретатору / rpath. Если это не сработает, вам придется продолжать исправлять его, пока не найдете путь, который действительно будет работать ... Ну, это не обязательно процесс проб и ошибок. Например, в примере с OP он нуженGLIBC_2.3
, чтобы вы могли легко найти, какая библиотека предоставляет эту версию, используяstrings
:Теоретически, первый grep будет пустым, потому что системный libc не имеет нужной версии, а второй должен вывести GLIBC_2.3, потому что он использует версию
myapp
, поэтому мы знаем, что мы можем использоватьpatchelf
наш двоичный файл по этому пути.Когда вы пытаетесь запустить бинарный файл в Linux, он пытается загрузить компоновщик, затем библиотеки, и все они должны быть в пути и / или в правильном месте. Если ваша проблема связана с компоновщиком, и вы хотите узнать, какой путь ищет ваш двоичный файл, вы можете узнать с помощью этой команды:
Если ваша проблема с библиотеками, команды, которые дадут вам используемые библиотеки:
В этом списке будут перечислены библиотеки, которые нужны вашему бинарному файлу, но вы, вероятно, уже знаете проблемные, поскольку они уже дают ошибки, как в случае с OP.
«patchelf» работает для многих различных проблем, с которыми вы можете столкнуться при попытке запустить программу, связанных с этими двумя проблемами. Например, если вы получаете:,
ELF file OS ABI invalid
это может быть исправлено путем установки нового загрузчика (--set-interpreter
часть команды), как я объясню здесь . Другой пример - проблема полученияNo such file or directory
когда вы запускаете файл, который существует и является исполняемым, как показано здесь . В этом конкретном случае у OP отсутствовала ссылка на загрузчик, но, возможно, в вашем случае у вас нет прав root и вы не можете создать ссылку. Установка нового переводчика решит вашу проблему.Спасибо Employed Russian и Михаилу Панкову за понимание и решение!
источник
patchelf
), но фраза «Нет необходимости ... редактировать двоичные файлы» может немного вводить в заблуждение (поскольку вы фактически редактируете свои двоичные файлы).Используйте LD_PRELOAD: поместите вашу библиотеку куда-нибудь из каталогов man lib и запустите:
Смотрите: статья в Википедии
источник
Прежде всего, наиболее важной зависимостью каждой динамически связанной программы является компоновщик. Все так библиотеки должны соответствовать версии компоновщика.
Давайте рассмотрим простой пример: у меня есть система Ubuntu Newset, на которой я запускаю какую-то программу (в моем случае это D-компилятор - ldc2). Я хотел бы запустить его на старой CentOS, но из-за старой библиотеки glibc это невозможно. я получил
Я должен скопировать все зависимости из Ubuntu в Centos. Правильный метод заключается в следующем:
Для начала давайте проверим все зависимости:
linux-vdso.so.1 - не настоящая библиотека, и нам не нужно об этом заботиться.
/lib64/ld-linux-x86-64.so.2 - это компоновщик, который используется linux для связи исполняемого файла со всеми динамическими библиотеками.
Остальные файлы являются настоящими библиотеками, и все они вместе с компоновщиком должны быть скопированы где-то в centos.
Предположим, что все библиотеки и компоновщик находятся в каталоге "/ mylibs".
ld-linux-x86-64.so.2 - как я уже сказал - это компоновщик. Это не динамическая библиотека, а статический исполняемый файл. Вы можете запустить его и увидеть, что у него даже есть некоторые параметры, например --library-path (я вернусь к нему).
В Linux динамически связанная программа может запускаться только по имени, например
Linux загружает такую программу в ОЗУ и проверяет, какой компоновщик для нее установлен. Обычно в 64-битной системе это /lib64/ld-linux-x86-64.so.2 (в вашей файловой системе это символическая ссылка на настоящий исполняемый файл). Затем linux запускает компоновщик и загружает динамические библиотеки.
Вы также можете немного изменить это и сделать такой трюк:
Это метод принуждения Linux к использованию конкретного компоновщика.
И теперь мы можем вернуться к упомянутому ранее параметру --library-path
Он запустит 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#Compile_against_glibc_in_an_installed_location Эти объекты выполняют раннюю настройку, на которую опирается glibc, поэтому я не удивлюсь, если что-нибудь не получится и удивительно тонкие способы.Для более надежной настройки см. Настройка 2 ниже.
Соберите glibc и установите локально:
Настройка 1: проверить сборку
test_glibc.c
Скомпилируйте и запустите с
test_glibc.sh
:Программа выводит ожидаемое:
Команда адаптирована из https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location, но
--sysroot
привела к ошибке:поэтому я убрал его.
ldd
output подтверждает, чтоldd
библиотеки и, которые мы только что создали, на самом деле используются, как и ожидалось:Результаты
gcc
отладки компиляции показывают, что использовались мои объекты среды выполнения хоста, что плохо, как упоминалось ранее, но я не знаю, как обойти это, например, оно содержит:Настройка 1: изменить glibc
Теперь давайте изменим glibc:
Затем перекомпилируйте и переустановите glibc, перекомпилируйте и перезапустите нашу программу:
и мы видим
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
флагов , что кажется странным, так как мы создали сам GCC. Но все, кажется, работает, так что это только неудобство.Получите crosstool-NG, настройте и соберите его:
Сборка занимает от тридцати минут до двух часов.
Единственный обязательный параметр конфигурации, который я вижу, - это соответствие версии ядра вашего хоста для использования правильных заголовков ядра. Найдите версию ядра своего хоста с помощью:
который показывает мне:
так что
menuconfig
я делаю:Operating System
Version of linux
поэтому я выбираю:
которая является первой равной или более старой версией. Он должен быть старше, поскольку ядро обратно совместимо.
Настройка 2: дополнительные конфигурации
То,
.config
что мы создали,./ct-ng x86_64-unknown-linux-gnu
имеет:Чтобы изменить это,
menuconfig
сделайте:C-library
Version of glibc
спасти
.config
и продолжить сборку.Или, если вы хотите использовать свой собственный исходный код glibc, например, использовать glibc из последней версии git, выполните следующее :
Paths and misc options
Try features marked as EXPERIMENTAL
: установить в trueC-library
Source of glibc
Custom location
: скажи даCustom location
Custom source location
: указать каталог, содержащий ваш исходный код glibcгде glibc был клонирован как:
Настройка 2: проверить это
После того, как вы соберете нужный набор инструментов, протестируйте его:
Кажется, все работает как в программе установки 1, за исключением того, что теперь использовались правильные объекты времени выполнения:
Установка 2: неудачная попытка перекомпиляции glibc
Это не представляется возможным с Crosstool-NG, как объяснено ниже.
Если вы просто перестроить;
тогда ваши изменения в пользовательском расположении исходного кода glibc будут приняты во внимание, но он строит все с нуля, что делает его непригодным для итеративной разработки.
Если мы делаем:
он дает хороший обзор шагов сборки:
следовательно, мы видим, что есть этапы glibc, переплетенные с несколькими этапами GCC, прежде всего это
libc_start_files
происходит раньшеcc_core_pass_2
, что, вероятно, является самым дорогим шагом вместе сcc_core_pass_1
.Чтобы построить только один шаг, вы должны сначала установить
.config
опцию «Сохранить промежуточные шаги» для начальной сборки:Paths and misc options
Debug crosstool-NG
Save intermediate steps
и тогда вы можете попробовать:
но, к сожалению,
+
требуется, как указано на: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536и в основном все еще делает перестройку слишком медленной, чтобы ее можно было реализовать для разработки, и я не вижу, как преодолеть это, не исправляя crosstool-NG.
Кроме того, начиная с
libc
шага, похоже, не копировать исходный кодCustom source location
, что делает этот метод непригодным для использования.Бонус: stdlibc ++
Бонус, если вы также заинтересованы в стандартной библиотеке C ++: Как редактировать и перестраивать исходный код стандартной библиотеки GCC libstdc ++ C ++?
источник
Можете ли вы рассмотреть возможность использования Nix http://nixos.org/nix/ ?
источник
@msb дает безопасное решение.
Я столкнулся с этой проблемой, когда я сделал
import tensorflow as tf
в среде Конда, вCentOS 6.5
которой только имеетglibc-2.12
.Я хочу предоставить некоторые детали:
Сначала установите
glibc
в свой домашний каталог:Во-вторых, следуйте тем же способом, чтобы установить patchelf ;
В-третьих, исправьте ваш Python:
как упомянуто @msb
Теперь я могу использовать
tensorflow-2.0 alpha
вCentOS 6.5
.ссылка: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/
источник
Я не уверен, что вопрос по-прежнему актуален, но есть и другой способ решения проблемы: Docker. Можно установить практически пустой контейнер исходного дистрибутива (дистрибутив, используемый для разработки) и скопировать файлы в контейнер. Таким образом, вам не нужно создавать файловую систему, необходимую для chroot.
источник
Если вы внимательно посмотрите на второй вывод, вы увидите, что используется новое расположение для библиотек. Возможно, все еще отсутствуют библиотеки, которые являются частью glibc.
Я также считаю, что все библиотеки, используемые вашей программой, должны быть скомпилированы с этой версией glibc. Если у вас есть доступ к исходному коду программы, лучшим решением будет новая компиляция.
источник
«Занятый русский» - один из лучших ответов, и я думаю, что все другие предложенные ответы могут не сработать. Причина в том, что когда приложение создается впервые, все необходимые ему API-интерфейсы разрешаются во время компиляции. Используя «ldd» вы можете увидеть все статически связанные зависимости:
Но во время выполнения firefox также загрузит много других динамических библиотек, например (для firefox) загружено много библиотек, помеченных «glib» (даже если статически связанных нет ни одной):
Много раз, вы можете видеть, как названия одной версии мягко связаны с другой версией. Например:
Следовательно, это означает, что в одной системе существуют разные версии «библиотек», что не является проблемой, поскольку это один и тот же файл, и это обеспечит совместимость, когда приложения имеют зависимости от нескольких версий.
Поэтому на системном уровне все библиотеки почти взаимозависимы, и простое изменение приоритета загрузки библиотек с помощью манипуляции 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 и т. д.).
источник
Когда я захотел запустить браузер chromium в Ubuntu (glibc-2.15), я получил (типичное) сообщение "... libc.so.6: версия` GLIBC_2.19 'не найдена ... ". Я учел тот факт, что файлы нужны не постоянно, а только для запуска. Поэтому я собрал файлы, необходимые для браузера и sudo, и создал среду mini-glibc-2.19, запустил браузер и снова скопировал исходные файлы. Необходимые файлы находятся в оперативной памяти, и оригинальный glibc такой же.
mkdir -p /glibc-2.19/i386-linux-gnu
mkdir -p /glibc-2.15/i386-linux-gnu
скрипт для запуска браузера:
источник