web-dev-qa-db-ger.com

Mehrere glibc-Bibliotheken auf einem einzigen Host

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

146
dogbane

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 .

205

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!

46
msb

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

17
PiedPiper

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.

6
Igor

Setup 1: kompiliere deine eigene glibc ohne dedizierten GCC und benutze sie

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`

Setup 1: Überprüfen Sie den Build

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

Setup 1: Glibc ändern

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.

Setup 2: Crosstool-NG makelloses Setup

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.

Setup 2: optionale Konfigurationen

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 setzen
  • C-library
    • Source of glibc
      • Custom location: Ja sagen
      • Custom location
        • Custom source location: Zeigen Sie auf ein Verzeichnis, das Ihre Glibc-Quelle enthält

wo glibc geklont wurde als:

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28

Setup 2: Probieren Sie es aus

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

Setup 2: Fehler beim erneuten Kompilieren von Glibc

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.

Bonus: stdlibc ++

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/

2
Belter

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.

2
user1396055

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.

1
rsarro

"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).

1
Peter Teoh

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
0
dudu