Кілька бібліотек glibc на одному хості


171

Кілька бібліотек 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 і не збираються звідки я їх поклав?

Дякую


1
та ж проблема з сервером SLES-11. Неможливо оновити та потрібні останні матеріали. о мій ...
UmNyobe

FWIW, export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH дійсно вирішити цю проблему для мене! Це, звичайно, не буде працювати для всіх, але це легко виправити, якщо він працює! Дякую! :)
rinogo

Відповіді:


229

В одній і тій же системі дуже можливо мати кілька версій 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

Параметр " -rpathLinker" змусить завантажувач виконувати пошук бібліотек у /path/to/newglibc(тому вам не доведеться встановлювати його LD_LIBRARY_PATHперед запуском), і -dynamic-linkerпараметр "випече" шлях для виправлення ld-linux.so.2в програму.

Якщо ви не можете повторно зв’язати myappпрограму (наприклад, тому, що це сторонній двійковий файл), не все втрачено, але воно стає складніше. Одне рішення - створити для цього належне chrootсередовище. Ще одна можливість - використовувати rtldi та бінарний редактор .


3
Зауважте, що -Wl,--dynamic-linker=file(займає два '-') працює лише під час компіляції для ELF-файлів. Перевірка/sbin/ldconfig -p | grep ld
Том

49
Тепер ви можете скористатися зручною утилітою patchelf( nixos.org/patchelf.html ), яка дозволяє змінювати rpath та інтерпретатор вже складеного ELF.
Михайло Паньков

10
Варто згадати, що вказівка ​​шляху до нового glibc з використанням, -Wl,--rpathа не LD_LIBRARY_PATHможе бути важливою з інших причин, ніж зручність: якщо програма запускає дочірні процеси, цінність LD_LIBRARY_PATHзазвичай їх успадковується, але якщо вони також не компільовані для використання новіший glibc (наприклад, якщо вони схожі на бінарні бінарні файли bash), вони не запускатимуться.
HighCommander4

13
Інший варіант - запуск нового ld.so безпосередньо, передаючи йому вашу двійкову програму як параметр; це ефективно замінить ld.so використаний без необхідності перекомпілювати програму:/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk


67

Це питання старе, інші відповіді - старі. Відповідь "працевлаштованої російської мови" є дуже хорошою та інформативною, але вона працює лише за наявності вихідного коду. Якщо ні, то альтернативи тоді були дуже хитрі. На щастя, сьогодні ми маємо просте рішення цієї проблеми (як коментується в одній з його відповідей), використовуючи patchelf . Все, що вам потрібно зробити, це:

$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp

Після цього ви можете просто виконати свій файл:

$ ./myapp

Не потрібно chrootчи вручну редагувати двійкові файли, на щастя. Але не забудьте створити резервну копію свого двійкового файлу перед тим, як виправити його, якщо ви не впевнені, що робите, оскільки він змінює ваш двійковий файл. Після цього ви не зможете відновити старий шлях до інтерпретатора / rpath. Якщо це не працює, вам доведеться продовжувати виправлення, поки ви не знайдете шлях, який насправді буде працювати ... Ну, це не повинен бути процесом проб і помилок. Наприклад, у прикладі ОП він потрібен GLIBC_2.3, тож ви можете легко знайти, який lib надає цю версію, використовуючиstrings :

$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3

Теоретично, перший греп буде порожнім, оскільки системний libc не має потрібної йому версії, а другий повинен вивести GLIBC_2.3, оскільки він має версію myapp , тож ми знаємо, що можемо patchelfнаш бінарний файл використовувати цей шлях.

Коли ви намагаєтеся запустити бінарний файл в Linux, двійковий файл намагається завантажити лінкер, потім бібліотеки, і всі вони повинні бути на шляху та / або в потрібному місці. Якщо у вас є проблема з посиланням, і ви хочете дізнатися, який шлях шукає ваш бінарний файл, ви можете дізнатися за допомогою цієї команди:

$ readelf -l myapp | grep interpreter
  [Requesting program interpreter: /lib/ld-linux.so.2]                                                                                                                                                                                   

Якщо у вас проблема з libs, командами, які дадуть вам використовувані libs, є:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Тут буде перераховано ті, що потрібні вашим бінарним файлам, але ви, мабуть, уже знаєте проблемні, оскільки вони вже приносять помилки, як у випадку з ОП.

"patchelf" працює для багатьох різних проблем, з якими ви можете зіткнутися під час спроби запустити програму, пов'язану з цими двома проблемами. Наприклад, якщо ви отримуєте:, ELF file OS ABI invalidце може бути виправлено, встановивши новий завантажувач ( --set-interpreterчастина команди), як я пояснюю тут . Інший приклад - це проблема отримання No such file or directoryпід час запуску файла, який там є і виконуваним, як приклад тут . У цьому конкретному випадку в OP відсутнє посилання на завантажувач, але, можливо, у вашому випадку ви не маєте кореневого доступу та не можете створити посилання. Встановлення нового перекладача вирішило б вашу проблему.

Дякую працевлаштованому росіянину та Михайлу Панькову за розуміння та рішення!


1
Це було найкорисніше! Я закріпив python binary, щоб використовувати новий glibc для tensorflow
faizan

Це акуратне рішення (про який я раніше не знав patchelf), але фраза "Не потрібно редагувати бінарні файли" може трохи ввести в оману (оскільки ви фактично редагуєте свої бінарні файли).
larsks

Там, зафіксовано. ;)
msb

Дійсно корисна утиліта! Дякую! Хоча мені вдалося отримати помилку сегментації лише через години ручного вирішення залежностей, а потім виправити все, щоб локально встановити хром без прав адміністратора ...
G. Bergeron

@fgiraldeau дякую за комплімент. :) але питання було задано, відповіли і прийняли у 2009 році, я не очікував, що хтось чекатиме 8 років, перш ніж приймати відповідь. heheh; D
msb

20

Використовуйте LD_PRELOAD: поставте свою бібліотеку кудись із каталогів man lib та запустіть:

LD_PRELOAD='mylibc.so anotherlib.so' program

Дивіться: стаття у Вікіпедії


1
думав, що це буде гарним вирішенням складного Makefile, але це не спрацювало для мене
galactica

це корисно, особливо для тих, хто не має джерела binary.thanks
кодер

2
гм ... я помилявся ,, здається, мені потрібно пройти шлях ld-linux.so до / path / to / new / lib / frist при компіляції джерела та зв’язуванні
coder

1
Це не працює, якщо ld - #. ##. Значить (від вашої системи glibc lib) не та сама версія glibc, як libc.so. # (від вашої альтернативної glibc lib)
Енді

12

Перш за все, найважливішою залежністю кожної динамічно пов'язаної програми є лінкер. Все так, що бібліотеки повинні відповідати версії посилання.

Візьмемо простий еппл: у мене є система newbuta ubuntu, де я запускаю якусь програму (у моєму випадку це компілятор 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 do виконуваного файлу з усіма динамічними бібліотеками.

Решта файлів - справжні бібліотеки, і всі вони разом із лінкером повинні бути скопійовані десь у центрі.

Припустимо, всі бібліотеки та посилання в каталозі "/ 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 використовувати певний лінкер.

І тепер ми можемо повернутися до згаданого раніше параметра - бібліотека-шлях

/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2

Він запустить ldc2 і завантажить динамічні бібліотеки з / mylibs.

Це спосіб викликати виконуваний файл з вибраними (не системними за замовчуванням) бібліотеками.


Я склав програму на RH7 і мені потрібно, щоб вона працювала на RH6. Я не хотів будувати новий виконуваний файл або використовувати patchelf, тому це чудова альтернатива.
Марк Райкок

9

Установка 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 та встановіть локально:

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.
     * /programming/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#Compile_against_glibc_in_an_installed_location, але --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прапорів , що дивно, оскільки ми створили 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
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

Побудова займає від тридцяти хвилин до двох годин.

Єдиний обов'язковий варіант конфігурації, який я бачу, - це узгодження вашої версії ядра хоста для використання правильних заголовків ядра. Знайдіть версію ядра хоста за допомогою:

uname -a

що показує мені:

4.15.0-34-generic

так що menuconfigя роблю:

  • Operating System
    • Version of linux

тому я вибираю:

4.14.71

що є першою рівною чи старшою версією. Він повинен бути старшим, оскільки ядро ​​назад сумісне.

Налаштування 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

Здається, все працює як у Setup 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

Це не здається можливим із кросстол-НГ, як пояснено нижче.

Якщо ви просто переобладнаєте;

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/isissue/1033#issuecomment-424877536

Однак зауважте, що перезапуск на проміжному кроці скидає інсталяційний каталог у стан, який він мав під час цього кроку. Тобто, у вас буде перебудований libc - але жоден остаточний компілятор не будується з цим libc (а значить, і жодної бібліотеки компілятора, як libstdc ++).

і в основному все ще робить відновлення занадто повільним, щоб бути можливим для розвитку, і я не бачу, як це подолати без виправлення кроссстол-НГ.

Крім того, починаючи з libcкроку, здавалося б, не копіюйте джерело знову Custom source location, зробивши цей метод непридатним.

Бонус: stdlibc ++

Бонус, якщо ви також зацікавлені у стандартній бібліотеці C ++: Як редагувати та відновлювати стандартний джерело бібліотеки GCC libstdc ++ C ++?


6

Чи можете ви розглянути можливість використання Nix http://nixos.org/nix/ ?

Nix підтримує багатокористувацьке управління пакетами: кілька користувачів можуть безпечно ділитися загальним магазином Nix, не потрібно мати кореневі привілеї для встановлення програмного забезпечення та можуть встановлювати та використовувати різні версії пакету.


4

@msb дає безпечне рішення.

Я зіткнувся з цією проблемою, коли я import tensorflow as tfбував у середовищі conda, в 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 .

ref: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/


2

Я не впевнений, що питання все ще актуальне, але є інший спосіб виправлення проблеми: Докер. Можна встановити майже порожній контейнер з розподілом джерел (дистрибутив, який використовується для розробки) і скопіювати файли в контейнер. Таким чином Вам не потрібно створювати файлову систему, необхідну для chroot.


1

Якщо уважно придивитись до другого виводу, то можна побачити, що використовується нове місце для бібліотек. Можливо, є ще відсутні бібліотеки, що входять до складу glibc.

Я також думаю, що всі бібліотеки, які використовуються у вашій програмі, повинні бути зібрані відповідно до цієї версії glibc. Якщо у вас є доступ до вихідного коду програми, свіжа компіляція виявляється найкращим рішенням.


1

"Російська працевлаштована" - одна з найкращих відповідей, і я думаю, що всі інші запропоновані відповіді можуть не спрацювати. Причина полягає лише в тому, що коли програма вперше створена, всі її API-інтерфейси вирішуються під час компіляції. Використовуючи "ldd" u, можна побачити всі статично пов'язані залежності:

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, або просто тар з існуючого середовища Distro. (наприклад, Fedora / Suse тощо).


0

Коли я хотів запустити Chrome-браузер на 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.