Plusieurs bibliothèques glibc sur un seul hôte
Mon serveur Linux (SLES-8) a actuellement glibc-2.2.5-235, mais j'ai un programme qui ne fonctionnera pas sur cette version et qui nécessite la glibc-2.3.3.
Est-il possible d'installer plusieurs glibcs sur le même hôte?
Voici l'erreur que j'obtiens lorsque j'exécute mon programme sur l'ancienne 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)
J'ai donc créé un nouveau répertoire appelé newglibc et copié les fichiers suivants dans:
libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so
et
export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH
Mais j'obtiens une erreur:
./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)
Il semble donc qu'ils sont toujours liés à / lib et ne reprennent pas d'où je les ai placés?
Merci
export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH
a résolu le problème pour moi! Cela ne fonctionnera certainement pas pour tout le monde, mais c'est une solution facile si cela fonctionne! Merci! :)Réponses:
Il est très possible d'avoir plusieurs versions de la glibc sur le même système (nous le faisons tous les jours).
Cependant, vous devez savoir que la glibc se compose de nombreux éléments (plus de 200 bibliothèques partagées) qui doivent tous correspondre. L'un des éléments est ld-linux.so.2, et il doit correspondre à libc.so.6, sinon vous verrez les erreurs que vous voyez.
Le chemin absolu vers ld-linux.so.2 est codé en dur dans l'exécutable au moment de la liaison, et ne peut pas être facilement modifié une fois la liaison établie.
Pour créer un exécutable qui fonctionnera avec la nouvelle glibc, procédez comme suit:
L'
-rpath
option de l'éditeur de liens permettra au chargeur d'exécution de rechercher des bibliothèques dans/path/to/newglibc
(vous n'aurez donc pas à définirLD_LIBRARY_PATH
avant de l'exécuter), et l'-dynamic-linker
option "bake" le chemin pour corrigerld-linux.so.2
dans l'application.Si vous ne pouvez pas relier l'
myapp
application (par exemple parce qu'il s'agit d'un binaire tiers), tout n'est pas perdu, mais cela devient plus compliqué. Une solution consiste à définir unchroot
environnement approprié pour cela. Une autre possibilité est d'utiliser rtldi et un éditeur binaire .la source
-Wl,--dynamic-linker=file
(prend deux '-') ne fonctionne que lors de la compilation pour les exécutables ELF. Check/sbin/ldconfig -p | grep ld
patchelf
( nixos.org/patchelf.html ), qui vous permet de modifier rpath et l'interpréteur d'ELF déjà compilé.-Wl,--rpath
plutôt queLD_LIBRARY_PATH
peut être important pour des raisons autres que de commodité: si le programme lance des processus enfants, la valeur deLD_LIBRARY_PATH
sera généralement héritée par eux, mais s'ils ne sont pas également compilés pour être utilisés la nouvelle glibc (par exemple, si ce sont des fichiers binaires commebash
), ils ne seront pas lancés./path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
-I
et-L
: stackoverflow.com/a/52454603/895245Cette question est ancienne, les autres réponses sont anciennes. La réponse de "Employed Russian" est très bonne et informative, mais elle ne fonctionne que si vous avez le code source. Si vous ne le faites pas, les alternatives à l'époque étaient très délicates. Heureusement, de nos jours, nous avons une solution simple à ce problème (comme commenté dans l'une de ses réponses), en utilisant patchelf . Tout ce que tu dois faire est:
Et après cela, vous pouvez simplement exécuter votre fichier:
Pas besoin de
chroot
modifier manuellement les binaires, heureusement. Mais n'oubliez pas de sauvegarder votre binaire avant de le patcher, si vous n'êtes pas sûr de ce que vous faites, car cela modifie votre fichier binaire. Après l'avoir corrigé, vous ne pouvez pas restaurer l'ancien chemin vers interpreter / rpath. Si cela ne fonctionne pas, vous devrez continuer à le corriger jusqu'à ce que vous trouviez le chemin qui fonctionnera réellement ... Eh bien, il n'est pas nécessaire que ce soit un processus d'essai et d'erreur. Par exemple, dans l'exemple d'OP, il en avait besoinGLIBC_2.3
, donc vous pouvez facilement trouver quelle bibliothèque fournit cette version en utilisantstrings
:En théorie, le premier grep serait vide parce que la libc système n'a pas la version qu'il veut, et le deuxième devrait afficher GLIBC_2.3 parce qu'il a la version
myapp
utilisée, donc nous savons que nous pouvonspatchelf
utiliser notre binaire en utilisant ce chemin.Lorsque vous essayez d'exécuter un binaire sous Linux, le binaire essaie de charger l'éditeur de liens, puis les bibliothèques, et elles devraient toutes être dans le chemin et / ou au bon endroit. Si votre problème concerne l'éditeur de liens et que vous souhaitez savoir quel chemin votre binaire recherche, vous pouvez le découvrir avec cette commande:
Si votre problème concerne les bibliothèques, les commandes qui vous donneront les bibliothèques utilisées sont:
Cela listera les bibliothèques dont votre binaire a besoin, mais vous connaissez probablement déjà celles qui posent problème, car elles génèrent déjà des erreurs comme dans le cas d'OP.
"patchelf" fonctionne pour de nombreux problèmes différents que vous pouvez rencontrer en essayant d'exécuter un programme, liés à ces 2 problèmes. Par exemple, si vous obtenez:,
ELF file OS ABI invalid
cela peut être corrigé en définissant un nouveau chargeur (la--set-interpreter
partie de la commande) comme je l'explique ici . Un autre exemple concerne le problème d'obtentionNo such file or directory
lorsque vous exécutez un fichier qui est là et exécutable, comme illustré ici . Dans ce cas particulier, OP manquait un lien vers le chargeur, mais peut-être que dans votre cas, vous n'avez pas d'accès root et ne pouvez pas créer le lien. La configuration d'un nouvel interprète résoudrait votre problème.Merci Employed Russian et Michael Pankov pour la perspicacité et la solution!
la source
patchelf
), mais la phrase "Pas besoin de ... modifier les binaires" peut être un peu trompeuse (puisque vous éditez en fait vos binaires).Utilisez LD_PRELOAD: placez votre bibliothèque quelque part hors des répertoires man lib et exécutez:
Voir: l'article Wikipedia
la source
Tout d'abord, la dépendance la plus importante de chaque programme lié dynamiquement est l'éditeur de liens. Toutes les bibliothèques doivent donc correspondre à la version de l'éditeur de liens.
Prenons un exemple simple: j'ai le système newset ubuntu où j'exécute un programme (dans mon cas, il s'agit du compilateur D - ldc2). J'aimerais l'exécuter sur l'ancien CentOS, mais à cause de l'ancienne bibliothèque glibc, c'est impossible. j'ai eu
Je dois copier toutes les dépendances d'ubuntu vers centos. La bonne méthode est la suivante:
Tout d'abord, vérifions toutes les dépendances:
linux-vdso.so.1 n'est pas une vraie bibliothèque et nous n'avons pas à nous en soucier.
/lib64/ld-linux-x86-64.so.2 est l'éditeur de liens, qui est utilisé par le linux pour lier l'exécutable à toutes les bibliothèques dynamiques.
Le reste des fichiers sont de vraies bibliothèques et tous avec l'éditeur de liens doivent être copiés quelque part dans les centos.
Supposons que toutes les bibliothèques et l'éditeur de liens se trouvent dans le répertoire "/ mylibs".
ld-linux-x86-64.so.2 - comme je l'ai déjà dit - est l'éditeur de liens. Ce n'est pas une bibliothèque dynamique mais un exécutable statique. Vous pouvez l'exécuter et voir qu'il a même des paramètres, par exemple --library-path (je vais y revenir).
Sur Linux, un programme lié dynamiquement peut être déjeuné simplement par son nom, par exemple
Linux charge ce programme dans la RAM et vérifie quel éditeur de liens est défini pour lui. Habituellement, sur un système 64 bits, il s'agit de /lib64/ld-linux-x86-64.so.2 (dans votre système de fichiers, il s'agit d'un lien symbolique vers l'exécutable réel). Ensuite, linux exécute l'éditeur de liens et charge les bibliothèques dynamiques.
Vous pouvez également changer cela un peu et faire une telle astuce:
C'est la méthode pour forcer le Linux à utiliser un éditeur de liens spécifique.
Et maintenant, nous pouvons revenir au paramètre mentionné précédemment --library-path
Il exécutera ldc2 et chargera les bibliothèques dynamiques depuis / mylibs.
C'est la méthode pour appeler l'exécutable avec les bibliothèques choisies (pas par défaut du système).
la source
Configuration 1: compilez votre propre glibc sans GCC dédié et utilisez-la
Cette configuration peut fonctionner et est rapide car elle ne recompile pas toute la chaîne d'outils GCC, juste la glibc.
Mais il n'est pas fiable car il utilise des objets d' exécution hôte C tels que
crt1.o
,crti.o
etcrtn.o
fourni par la glibc. Ceci est mentionné sur: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Ces objets effectuent une configuration précoce sur laquelle la glibc s'appuie, donc je ne serais pas surpris si les choses se plantaient merveilleusement et des manières incroyablement subtiles.Pour une configuration plus fiable, voir Configuration 2 ci-dessous.
Construisez la glibc et installez localement:
Configuration 1: vérifier la construction
test_glibc.c
Compilez et exécutez avec
test_glibc.sh
:Le programme produit les résultats attendus:
Commande adaptée de https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location mais l'a
--sysroot
fait échouer avec:alors je l'ai enlevé.
ldd
La sortie confirme que lesldd
bibliothèques et que nous venons de créer sont en fait utilisées comme prévu:La
gcc
sortie de débogage de compilation montre que mes objets d'exécution hôte ont été utilisés, ce qui est mauvais comme mentionné précédemment, mais je ne sais pas comment contourner cela, par exemple, il contient:Configuration 1: modifier la glibc
Modifions maintenant la glibc avec:
Puis recompilez et réinstallez la glibc, puis recompilez et relancez notre programme:
et nous voyons
hacked
imprimé quelques fois comme prévu.Cela confirme en outre que nous avons effectivement utilisé la glibc que nous avons compilée et non l'hôte.
Testé sur Ubuntu 18.04.
Configuration 2: configuration vierge du crosstool-NG
Ceci est une alternative à la configuration 1, et il est le plus correct configuration que j'ai accompli jusqu'à présent: tout est correct pour autant que je peux observer, y compris l'exécution de C des objets tels que
crt1.o
,crti.o
etcrtn.o
.Dans cette configuration, nous compilerons une chaîne d'outils GCC dédiée complète qui utilise la glibc que nous voulons.
Le seul inconvénient de cette méthode est que la construction prendra plus de temps. Mais je ne risquerais pas une configuration de production avec rien de moins.
crosstool-NG est un ensemble de scripts qui télécharge et compile tout à partir de la source pour nous, y compris GCC, glibc et binutils.
Oui, le système de construction de GCC est si mauvais que nous avons besoin d'un projet séparé pour cela.
Cette configuration n'est pas parfaite car crosstool-NG ne prend pas en charge la construction des exécutables sans
-Wl
drapeaux supplémentaires , ce qui semble étrange puisque nous avons construit GCC lui-même. Mais tout semble fonctionner, ce n'est donc qu'un inconvénient.Obtenez crosstool-NG, configurez-le et construisez-le:
La construction prend environ trente minutes à deux heures.
La seule option de configuration obligatoire que je peux voir est de faire correspondre la version de votre noyau hôte pour utiliser les en-têtes de noyau corrects. Trouvez la version de votre noyau hôte avec:
ce qui me montre:
donc dans
menuconfig
je fais:Operating System
Version of linux
donc je sélectionne:
qui est la première version égale ou antérieure. Il doit être plus ancien car le noyau est rétrocompatible.
Configuration 2: configurations optionnelles
Le
.config
que nous avons généré avec./ct-ng x86_64-unknown-linux-gnu
a:Pour changer cela,
menuconfig
faites:C-library
Version of glibc
sauver le
.config
et poursuivez la construction.Ou, si vous souhaitez utiliser votre propre source glibc, par exemple pour utiliser la glibc à partir du dernier git, procédez comme suit :
Paths and misc options
Try features marked as EXPERIMENTAL
: défini sur trueC-library
Source of glibc
Custom location
: dis ouiCustom location
Custom source location
: pointez sur un répertoire contenant votre source glibcoù la glibc a été clonée comme:
Configuration 2: testez-le
Une fois que vous avez construit la chaîne d'outils que vous souhaitez, testez-la avec:
Tout semble fonctionner comme dans la configuration 1, sauf que maintenant les objets d'exécution corrects ont été utilisés:
Configuration 2: échec de la tentative de recompilation efficace de la glibc
Cela ne semble pas possible avec le crosstool-NG, comme expliqué ci-dessous.
Si vous venez de reconstruire;
alors vos modifications apportées à l'emplacement de la source glibc personnalisée sont prises en compte, mais il construit tout à partir de zéro, le rendant inutilisable pour le développement itératif.
Si nous faisons:
cela donne un bon aperçu des étapes de construction:
par conséquent, nous voyons qu'il y a des étapes de la glibc entrelacées avec plusieurs étapes GCC, notamment
libc_start_files
vient avantcc_core_pass_2
, ce qui est probablement l'étape la plus coûteuse aveccc_core_pass_1
.Afin de ne construire qu'une seule étape, vous devez d'abord définir l'
.config
option "Enregistrer les étapes intermédiaires" dans l' option pour la construction initiale:Paths and misc options
Debug crosstool-NG
Save intermediate steps
et ensuite vous pouvez essayer:
mais malheureusement, le
+
requis comme mentionné à: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536et rend fondamentalement encore la reconstruction trop lente pour être faisable pour le développement, et je ne vois pas comment surmonter cela sans patcher crosstool-NG.
De plus, à partir de l'
libc
étape ne semblait pas recopier la sourceCustom source location
, ce qui rendait cette méthode inutilisable.Bonus: stdlibc ++
Un bonus si vous êtes également intéressé par la bibliothèque standard C ++: Comment éditer et reconstruire la source de la bibliothèque standard C ++ libstdc ++ de GCC?
la source
Pouvez-vous envisager d'utiliser Nix http://nixos.org/nix/ ?
la source
@msb donne une solution sûre.
J'ai rencontré ce problème lorsque je l'ai fait
import tensorflow as tf
dans un environnement conda dansCentOS 6.5
lequel seulementglibc-2.12
.Je souhaite fournir quelques détails:
Installez d'abord
glibc
dans votre répertoire personnel:Deuxièmement, suivez la même méthode pour installer patchelf ;
Troisièmement, corrigez votre Python:
comme mentionné par @msb
Maintenant je peux utiliser
tensorflow-2.0 alpha
dansCentOS 6.5
.réf: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/
la source
Je ne suis pas sûr que la question soit toujours d'actualité, mais il existe un autre moyen de résoudre le problème: Docker. On peut installer un conteneur presque vide de la distribution source (la distribution utilisée pour le développement) et copier les fichiers dans le conteneur. De cette façon, vous n'avez pas besoin de créer le système de fichiers nécessaire au chroot.
la source
Si vous regardez attentivement la deuxième sortie, vous pouvez voir que le nouvel emplacement des bibliothèques est utilisé. Peut-être qu'il manque encore des bibliothèques faisant partie de la glibc.
Je pense également que toutes les bibliothèques utilisées par votre programme devraient être compilées avec cette version de la glibc. Si vous avez accès au code source du programme, une nouvelle compilation semble être la meilleure solution.
la source
"Employé russe" est l'une des meilleures réponses, et je pense que toutes les autres réponses suggérées peuvent ne pas fonctionner. La raison en est simplement que lorsqu'une application est créée pour la première fois, toutes les API dont elle a besoin sont résolues au moment de la compilation. En utilisant "ldd", vous pouvez voir toutes les dépendances liées statiquement:
Mais au moment de l'exécution, Firefox chargera également de nombreuses autres bibliothèques dynamiques, par exemple (pour Firefox) il y a beaucoup de bibliothèques étiquetées "glib" chargées (même s'il n'y en a pas de lien statique):
Plusieurs fois, vous pouvez voir les noms d'une version liée à une autre version. Par exemple:
Cela signifie donc que différentes versions de "bibliothèques" existent dans un système - ce qui n'est pas un problème car il s'agit du même fichier, et cela fournira des compatibilités lorsque les applications ont plusieurs dépendances de versions.
Par conséquent, au niveau du système, toutes les bibliothèques sont presque interdépendantes les unes des autres, et le simple fait de changer la priorité de chargement des bibliothèques en manipulant LD_PRELOAD ou LD_LIBRARY_PATH n'aidera pas - même si elle peut se charger, elle risque toujours de planter.
http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc
La meilleure alternative est chroot (brièvement mentionnée par ER): mais pour cela, vous devrez recréer tout l'environnement dans lequel se trouve l'exécutable binaire d'origine - généralement à partir de / lib, / usr / lib /, / usr / lib / x86 etc. Vous pouvez soit utiliser "Buildroot", soit YoctoProject, soit simplement tar depuis un environnement Distro existant. (comme Fedora / Suse, etc.).
la source
Quand je voulais lancer un navigateur chrome sur Ubuntu précis (glibc-2.15), j'ai reçu le message (typique) "... libc.so.6: version` GLIBC_2.19 'not found ... ". J'ai pris en compte le fait que les fichiers ne sont pas nécessaires en permanence, mais uniquement pour commencer. J'ai donc rassemblé les fichiers nécessaires pour le navigateur et sudo et créé un environnement mini-glibc-2.19-, démarré le navigateur, puis copié à nouveau les fichiers d'origine. Les fichiers nécessaires sont dans la RAM et la glibc d'origine est la même.
mkdir -p /glibc-2.19/i386-linux-gnu
mkdir -p /glibc-2.15/i386-linux-gnu
le script pour exécuter le navigateur:
la source