Mehrere glibc-Bibliotheken auf einem einzigen Host
Mein Linux-Server (SLES-8) hat derzeit glibc-2.2.5-235, aber ich habe ein Programm, das auf dieser Version nicht funktioniert und glibc-2.3.3 benötigt.
Ist es möglich, mehrere Glibcs auf demselben Host zu installieren?
Dies ist der Fehler, den ich bekomme, wenn ich mein Programm auf der alten glibc ausführe:
./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)
Also habe ich ein neues Verzeichnis namens newglibc erstellt und die folgenden Dateien kopiert:
libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so
und
export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH
Aber ich bekomme einen Fehler:
./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)
Es sieht also so aus, als würden sie immer noch auf/lib verlinken und nicht abholen, wo ich sie abgelegt habe?
Vielen Dank
Es ist sehr gut möglich, mehrere Versionen von glibc auf demselben System zu haben (das machen wir jeden Tag).
Sie müssen jedoch wissen, dass glibc aus vielen Teilen besteht (über 200 gemeinsam genutzte Bibliotheken), die alle übereinstimmen müssen. Eines der Teile ist ld-linux.so.2, und es muss mit libc.so.6 übereinstimmen , sonst werden Sie die Fehler sehen, die Sie sind Sehen.
Der absolute Pfad zu ld-linux.so.2 ist zum Zeitpunkt der Verknüpfung fest in der ausführbaren Datei codiert und kann nach Abschluss der Verknüpfung nicht einfach geändert werden.
Gehen Sie folgendermaßen vor, um eine ausführbare Datei zu erstellen, die mit der neuen glibc funktioniert:
g++ main.o -o myapp ... \
-Wl,--rpath=/path/to/newglibc \
-Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2
Die Linkeroption -rpath
Veranlasst den Runtime Loader, nach Bibliotheken in /path/to/newglibc
Zu suchen (Sie müssten also nicht LD_LIBRARY_PATH
Einstellen, bevor Sie es ausführen), und die Linkeroption -dynamic-linker
"backt" den Pfad, um ld-linux.so.2
in der Anwendung zu korrigieren.
Wenn Sie die Anwendung myapp
nicht erneut verknüpfen können (z. B. weil es sich um eine Drittanbieter-Binärdatei handelt), ist nicht alles verloren, aber es wird schwieriger. Eine Lösung besteht darin, eine geeignete chroot
Umgebung dafür festzulegen. Eine andere Möglichkeit ist die Verwendung von rtldi und Binäreditor .
Diese Frage ist alt, die anderen Antworten sind alt. Die Antwort von "Employed Russian" ist sehr gut und informativ, funktioniert aber nur, wenn Sie den Quellcode haben. Wenn nicht, waren die Alternativen damals sehr knifflig. Glücklicherweise haben wir heutzutage eine einfache Lösung für dieses Problem (wie in einer seiner Antworten kommentiert), indem wir patchelf verwenden. Alles was du tun musst, ist:
$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp
Und danach können Sie einfach Ihre Datei ausführen:
$ ./myapp
Zum Glück müssen Sie die Binärdateien nicht chroot
oder manuell bearbeiten. Denken Sie jedoch daran, Ihre Binärdatei vor dem Patchen zu sichern, wenn Sie sich nicht sicher sind, was Sie tun, da dadurch Ihre Binärdatei geändert wird. Nach dem Patchen kann der alte Pfad zu Interpreter/Pfad nicht wiederhergestellt werden. Wenn es nicht funktioniert, müssen Sie es so lange patchen, bis Sie den Pfad gefunden haben, der tatsächlich funktioniert ... Nun, es muss kein Versuch-und-Irrtum-Prozess sein. Zum Beispiel benötigte er in OPs Beispiel GLIBC_2.3
, damit Sie mit strings
leicht herausfinden können, welche Bibliothek diese Version bietet:
$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3
Theoretisch würde das erste grep leer werden, weil die System-libc nicht die von ihm gewünschte Version hat, und das zweite sollte GLIBC_2.3 ausgeben, weil es die von myapp
verwendete Version hat, damit wir wissen, dass wir das können patchelf
unsere Binärdatei, die diesen Pfad verwendet.
Wenn Sie versuchen, eine Binärdatei unter Linux auszuführen, versucht die Binärdatei, den Linker und dann die Bibliotheken zu laden, und alle sollten sich im Pfad und/oder an der richtigen Stelle befinden. Wenn Ihr Problem mit dem Linker besteht und Sie herausfinden möchten, nach welchem Pfad Ihre Binärdatei sucht, können Sie dies mit dem folgenden Befehl herausfinden:
$ readelf -l myapp | grep interpreter
[Requesting program interpreter: /lib/ld-linux.so.2]
Wenn Ihr Problem bei den Bibliotheken liegt, sind die Befehle, mit denen Sie die verwendeten Bibliotheken erhalten, folgende:
$ readelf -d myapp | grep Shared
$ ldd myapp
Dies listet die Bibliotheken auf, die Ihre Binärdatei benötigt, aber Sie kennen wahrscheinlich bereits die problematischen, da sie bereits Fehler liefern, wie im Fall von OP.
"patchelf" funktioniert für viele verschiedene Probleme, die beim Ausführen eines Programms auftreten können, die mit diesen beiden Problemen zusammenhängen. Wenn Sie zum Beispiel Folgendes erhalten: ELF file OS ABI invalid
, kann durch Setzen eines neuen Loaders (der --set-interpreter
Teil des Befehls), wie ich erkläre hier . Ein weiteres Beispiel ist das Problem, No such file or directory
, wenn Sie eine Datei ausführen, die vorhanden und ausführbar ist, wie im Beispiel dargestellt hier . In diesem speziellen Fall fehlte OP eine Verknüpfung zum Loader, aber in Ihrem Fall haben Sie möglicherweise keinen Root-Zugriff und können die Verknüpfung nicht erstellen. Das Einstellen eines neuen Interpreters würde Ihr Problem lösen.
Vielen Dank an Employed Russian und Michael Pankov für die Einsicht und Lösung!
Verwenden Sie LD_PRELOAD: Platzieren Sie Ihre Bibliothek außerhalb der Verzeichnisse von man lib und führen Sie Folgendes aus:
LD_PRELOAD='mylibc.so anotherlib.so' program
Siehe: der Wikipedia-Artikel
Zuallererst ist die wichtigste Abhängigkeit jedes dynamisch verknüpften Programms der Linker. Alle Bibliotheken müssen mit der Version des Linkers übereinstimmen.
Nehmen wir ein einfaches Beispiel: Ich habe das neue Ubuntu-System, auf dem ich ein Programm ausführe (in meinem Fall ist es D-Compiler - ldc2). Ich würde es gerne auf dem alten CentOS laufen lassen, aber wegen der älteren glibc-Bibliothek ist es unmöglich. ich habe
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)
Ich muss alle Abhängigkeiten von Ubuntu zu Centos kopieren. Die richtige Methode ist folgende:
Überprüfen wir zunächst alle Abhängigkeiten:
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 ist keine echte Bibliothek und wir müssen uns nicht darum kümmern.
/lib64/ld-linux-x86-64.so.2 ist der Linker, mit dem Linux die ausführbare Datei mit allen dynamischen Bibliotheken verknüpft.
Die restlichen Dateien sind echte Bibliotheken und alle zusammen mit dem Linker müssen irgendwo in den Centos kopiert werden.
Angenommen, alle Bibliotheken und Linker befinden sich im Verzeichnis "/ mylibs".
ld-linux-x86-64.so.2 ist - wie ich bereits sagte - der Linker. Es ist keine dynamische Bibliothek, sondern eine statische ausführbare Datei. Sie können es ausführen und sehen, dass es sogar einige Parameter hat, zB --library-path (ich werde darauf zurückkommen).
Unter Linux kann ein dynamisch verknüpftes Programm nur nach seinem Namen zu Mittag gegessen werden, z
/bin/ldc2
Linux lädt ein solches Programm in den Arbeitsspeicher und überprüft, welcher Linker dafür eingestellt ist. Auf einem 64-Bit-System ist es normalerweise /lib64/ld-linux-x86-64.so.2 (in Ihrem Dateisystem ist es eine symbolische Verknüpfung zur tatsächlichen ausführbaren Datei). Dann führt Linux den Linker aus und lädt dynamische Bibliotheken.
Sie können dies auch ein wenig ändern und einen solchen Trick machen:
/mylibs/ld-linux-x86-64.so.2 /bin/ldc2
Dies ist die Methode, mit der Linux gezwungen wird, einen bestimmten Linker zu verwenden.
Und jetzt können wir zum erwähnten früheren Parameter --library-path zurückkehren
/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2
Es wird ldc2 ausführen und dynamische Bibliotheken aus/mylibs laden.
Dies ist die Methode zum Aufrufen der ausführbaren Datei mit ausgewählten (nicht den Systemstandardwerten entsprechenden) Bibliotheken.
Können Sie erwägen, Nix http://nixos.org/nix/ zu verwenden?
Nix unterstützt die Verwaltung von Paketen für mehrere Benutzer: Mehrere Benutzer können einen gemeinsamen Nix-Speicher sicher gemeinsam nutzen, benötigen keine Root-Berechtigungen, um Software zu installieren, und können verschiedene Versionen eines Pakets installieren und verwenden.
Dieses Setup funktioniert möglicherweise und ist schnell, da es nicht die gesamte GCC-Toolchain neu kompiliert, sondern nur glibc.
Es ist jedoch nicht zuverlässig, da es Host-C-Laufzeitobjekte wie crt1.o
, crti.o
Und crtn.o
Verwendet, die von glibc bereitgestellt werden. Dies wird erwähnt unter: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Diese Objekte werden früh ausgeführt Setup, auf das sich glibc verlässt, also wäre ich nicht überrascht, wenn die Dinge auf wundervolle und unglaublich subtile Weise abstürzen würden.
Für eine zuverlässigere Einrichtung siehe Einrichtung 2 unten.
Erstellen Sie glibc und installieren Sie es lokal:
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`
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://stackoverflow.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);
}
Kompiliere und starte mit 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
Das Programm gibt das erwartete aus:
gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674
Befehl angepasst von https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location aber --sysroot
schlug fehl mit:
cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install
also habe ich es entfernt.
Die Ausgabe von ldd
bestätigt, dass die soeben erstellten ldd
und Bibliotheken tatsächlich wie erwartet verwendet werden:
+ 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)
Die Kompilierungs-Debug-Ausgabe von gcc
zeigt, dass meine Host-Laufzeitobjekte verwendet wurden, was, wie bereits erwähnt, schlecht ist, aber ich weiß nicht, wie ich es umgehen soll, z. es beinhaltet:
COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o
Jetzt ändern wir glibc mit:
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)");
Dann kompiliere und installiere glibc neu und kompiliere und führe unser Programm erneut aus:
cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh
und wir sehen hacked
einige Male wie erwartet gedruckt.
Dies bestätigt weiter, dass wir tatsächlich die von uns kompilierte glibc verwendet haben und nicht die Host-Version.
Getestet unter Ubuntu 18.04.
Dies ist eine Alternative zu Setup 1 und es ist das korrekteste Setup, das ich bisher erreicht habe: Alles ist korrekt, soweit ich es beobachten kann, einschließlich der C-Laufzeitobjekte wie crt1.o
, crti.o
und crtn.o
.
In diesem Setup kompilieren wir eine vollständige dedizierte GCC-Toolchain, die die gewünschte Glibc verwendet.
Der einzige Nachteil dieser Methode ist, dass der Build länger dauert. Aber ich würde kein Produktionssetup mit weniger riskieren.
crosstool-NG ist eine Sammlung von Skripten, die für uns alles aus dem Quellcode herunterladen und kompilieren, einschließlich GCC, glibc und binutils.
Ja, das GCC-Build-System ist so schlecht, dass wir dafür ein separates Projekt benötigen.
Dieses Setup ist nur nicht perfekt, weil crosstool-NG das Erstellen der ausführbaren Dateien ohne zusätzliche -Wl
- Flags nicht unterstützt. habe GCC selbst gebaut. Aber alles scheint zu funktionieren, das ist nur eine Unannehmlichkeit.
Holen Sie sich crosstool-NG, konfigurieren und erstellen Sie es:
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`
Der Bau dauert ungefähr dreißig Minuten bis zwei Stunden.
Die einzige obligatorische Konfigurationsoption, die ich sehen kann, besteht darin, dass sie mit Ihrer Host-Kernel-Version übereinstimmt, um die richtigen Kernel-Header zu verwenden. Finden Sie Ihre Host-Kernel-Version mit:
uname -a
das zeigt mir:
4.15.0-34-generic
also in menuconfig
mache ich:
Operating System
Version of linux
also wähle ich:
4.14.71
das ist die erste gleiche oder ältere Version. Es muss älter sein, da der Kernel abwärtskompatibel ist.
Der .config
, Den wir mit ./ct-ng x86_64-unknown-linux-gnu
Generiert haben, hat:
CT_GLIBC_V_2_27=y
Um dies zu ändern, gehen Sie in menuconfig
wie folgt vor:
C-library
Version of glibc
speichern Sie den .config
und fahren Sie mit dem Build fort.
Oder wenn Sie Ihre eigene Glibc-Quelle verwenden möchten, z. Um glibc von der neuesten Version zu verwenden, gehen Sie wie folgt vor :
Paths and misc options
Try features marked as EXPERIMENTAL
: Auf true setzenC-library
Source of glibc
Custom location
: Ja sagenCustom location
Custom source location
: Zeigen Sie auf ein Verzeichnis, das Ihre Glibc-Quelle enthältwo glibc geklont wurde als:
git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
Sobald Sie die gewünschte Toolchain erstellt haben, testen Sie sie mit:
#!/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
Alles scheint wie in Setup 1 zu funktionieren, außer dass jetzt die richtigen Laufzeitobjekte verwendet wurden:
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
Mit Crosstool-NG scheint dies nicht möglich zu sein, wie weiter unten erläutert.
Wenn Sie nur neu erstellen;
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`
dann werden Ihre Änderungen am benutzerdefinierten glibc-Quellspeicherort berücksichtigt, es wird jedoch alles von Grund auf neu erstellt, sodass es für die iterative Entwicklung unbrauchbar wird.
Wenn wir es tun:
./ct-ng list-steps
es gibt einen schönen Überblick über die Build-Schritte:
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.
daher sehen wir, dass es glibc-Schritte gibt, die mit mehreren GCC-Schritten verflochten sind, insbesondere libc_start_files
kommt vor cc_core_pass_2
, was zusammen mit cc_core_pass_1
wahrscheinlich der teuerste Schritt ist.
Um nur einen Schritt zu erstellen, müssen Sie zuerst die Option "Zwischenschritte speichern" in .config
Für den ersten Build festlegen:
Paths and misc options
Debug crosstool-NG
Save intermediate steps
und dann kannst du versuchen:
env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`
aber leider ist der +
erforderlich wie erwähnt unter: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536
Beachten Sie jedoch, dass durch einen Neustart in einem Zwischenschritt das Installationsverzeichnis auf den Status zurückgesetzt wird, den es in diesem Schritt hatte. Das heißt, Sie werden eine neu erstellte libc haben - aber keinen endgültigen Compiler, der mit dieser libc erstellt wurde (und daher auch keine Compiler-Bibliotheken wie libstdc ++).
und im Grunde macht die Neuerstellung immer noch zu langsam, um für die Entwicklung durchführbar zu sein, und ich sehe keinen Weg, dies zu überwinden, ohne Crosstool-NG zu patchen.
Darüber hinaus schien es nicht so zu sein, dass ab dem Schritt libc
die Quelle erneut aus Custom source location
Kopiert wurde, wodurch diese Methode unbrauchbar wurde.
Ein Bonus, wenn Sie sich auch für die C++ - Standardbibliothek interessieren: Wie kann man die GCC libstdc ++ C++ - Standardbibliothek bearbeiten und neu erstellen?
@msb gibt eine sichere Lösung.
Ich bin auf dieses Problem gestoßen, als ich import tensorflow as tf
In einer Conda-Umgebung in CentOS 6.5
Ausgeführt habe, die nur glibc-2.12
Enthält.
ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/
Ich möchte einige Details liefern:
Installieren Sie zuerst glibc
in Ihrem Home-Verzeichnis:
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
Zweitens gehen Sie genauso vor, um patchelf zu installieren.
Drittens patchen Sie Ihre Python:
[[email protected] ~]$ 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
wie von @msb erwähnt
Jetzt kann ich tensorflow-2.0 alpha
In CentOS 6.5
Verwenden.
ref: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/
Ich bin nicht sicher, ob die Frage noch relevant ist, aber es gibt eine andere Möglichkeit, das Problem zu beheben: Docker. Man kann einen fast leeren Container der Quelldistribution (die für die Entwicklung verwendete Distribution) installieren und die Dateien in den Container kopieren. Auf diese Weise müssen Sie nicht das für chroot erforderliche Dateisystem erstellen.
Wenn Sie sich die zweite Ausgabe genau ansehen, sehen Sie, dass der neue Speicherort für die Bibliotheken verwendet wird. Vielleicht fehlen noch Bibliotheken, die Teil des glibc sind.
Ich denke auch, dass alle von Ihrem Programm verwendeten Bibliotheken gegen diese Version von glibc kompiliert werden sollten. Wenn Sie Zugriff auf den Quellcode des Programms haben, scheint eine neue Kompilierung die beste Lösung zu sein.
"Angestelltes Russisch" ist eine der besten Antworten, und ich denke, alle anderen vorgeschlagenen Antworten funktionieren möglicherweise nicht. Der Grund liegt einfach darin, dass beim erstmaligen Erstellen einer Anwendung alle benötigten APIs zum Zeitpunkt der Kompilierung aufgelöst werden. Mit "ldd" können Sie alle statisch verknüpften Abhängigkeiten sehen:
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)
Zur Laufzeit lädt Firefox jedoch auch viele andere dynamische Bibliotheken, z. B. (für Firefox) sind viele mit "glib" gekennzeichnete Bibliotheken geladen (obwohl statisch verknüpft, gibt es keine):
/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
Häufig können Sie die Namen einer Version sehen, die mit einer anderen Version verknüpft ist. Z.B:
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
Dies bedeutet, dass in einem System unterschiedliche Versionen von "Bibliotheken" vorhanden sind. Dies ist kein Problem, da es sich um dieselbe Datei handelt. Außerdem werden Kompatibilitäten bereitgestellt, wenn Anwendungen mehrere Versionsabhängigkeiten aufweisen.
Daher sind auf Systemebene alle Bibliotheken fast voneinander abhängig, und nur das Ändern der Ladepriorität der Bibliotheken durch Manipulieren von LD_PRELOAD oder LD_LIBRARY_PATH hilft nicht - selbst wenn sie geladen werden können, kann es zur Laufzeit immer noch zum Absturz kommen.
http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc
Die beste Alternative ist chroot (von ER kurz erwähnt): Dazu müssen Sie jedoch die gesamte Umgebung neu erstellen, in der die ursprüngliche Binärdatei ausgeführt wird - normalerweise beginnend mit/lib,/usr/lib /,/usr/lib/x86 usw. Sie können entweder "Buildroot" oder YoctoProject oder nur tar aus einer vorhandenen Distro-Umgebung verwenden. (wie Fedora/Suse etc).
Als ich einen Chrom-Browser auf Ubuntu Precise (glibc-2.15) ausführen wollte, bekam ich die (typische) Meldung "... libc.so.6: Version` GLIBC_2.19 'nicht gefunden ... ". Ich habe die Tatsache berücksichtigt, dass Dateien nicht permanent benötigt werden, sondern nur zum Starten. Also habe ich die für den Browser und Sudo benötigten Dateien gesammelt und eine mini-glibc-2.19-Umgebung erstellt, den Browser gestartet und dann die Originaldateien wieder zurückkopiert. Die benötigten Dateien befinden sich in RAM und die ursprüngliche Glibc ist dieselbe.
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)
das Skript zum Ausführen des Browsers:
#!/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