Múltiples bibliotecas glibc en un solo host

171

Múltiples bibliotecas glibc en un solo host

Mi servidor Linux (SLES-8) actualmente tiene glibc-2.2.5-235, pero tengo un programa que no funcionará en esta versión y requiere glibc-2.3.3.

¿Es posible tener múltiples glibcs ​​instalados en el mismo host?

Este es el error que obtengo cuando ejecuto mi programa en el viejo 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)

Así que creé un nuevo directorio llamado newglibc y copié los siguientes archivos en:

libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so

y

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

Pero me sale un error:

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

Entonces, ¿parece que todavía están vinculados a / lib y no se están recuperando de donde los puse?

Gracias

dogbane
fuente
1
mismo problema con el servidor SLES-11. No se puede actualizar y necesita cosas recientes. oh mi ...
UmNyobe
Fwiw, export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH hizo resolver el problema para mí! Ciertamente no funcionará para todos, ¡pero es una solución fácil si funciona! ¡Gracias! :)
rinogo

Respuestas:

229

Es muy posible tener múltiples versiones de glibc en el mismo sistema (lo hacemos todos los días).

Sin embargo, debe saber que glibc consta de muchas piezas (más de 200 bibliotecas compartidas) que todas deben coincidir. Una de las piezas es ld-linux.so.2, y debe coincidir con libc.so.6, o verá los errores que está viendo.

La ruta absoluta a ld-linux.so.2 está codificada en el ejecutable en el momento del enlace, y no se puede cambiar fácilmente una vez que se realiza el enlace.

Para construir un ejecutable que funcione con el nuevo glibc, haga esto:

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

La -rpathopción del vinculador hará que el cargador de tiempo de ejecución busque bibliotecas en /path/to/newglibc(para que no tenga que configurar LD_LIBRARY_PATHantes de ejecutarlo), y la -dynamic-linkeropción "horneará" la ruta para corregir ld-linux.so.2en la aplicación.

Si no puede volver a vincular la myappaplicación (por ejemplo, porque es un binario de terceros), no todo se pierde, pero se vuelve más complicado. Una solución es establecer un chrootentorno adecuado para ello. Otra posibilidad es usar rtldi y un editor binario .

Ruso empleado
fuente
3
Tenga en cuenta que -Wl,--dynamic-linker=file(toma dos '-') solo funciona al compilar ejecutables ELF. Comprobación/sbin/ldconfig -p | grep ld
Tom
49
Ahora puede usar una práctica utilidad patchelf( nixos.org/patchelf.html ), que le permite modificar rpath e intérprete de ELF ya compilado.
Michael Pankov
10
Vale la pena mencionar que especificar la ruta al nuevo glibc usando en -Wl,--rpathlugar de LD_LIBRARY_PATHpuede ser importante por razones distintas a la conveniencia: si el programa inicia procesos secundarios, el valor de LD_LIBRARY_PATHusualmente será heredado por ellos, pero si no están compilados para usar el glibc más nuevo (por ejemplo, si son binarios de stock como bash), no se lanzarán.
HighCommander4
13
Otra opción es ejecutar el nuevo ld.so directamente, pasándole su programa binario como parámetro; esto reemplazará efectivamente ld.so utilizado sin la necesidad de recompilar el programa:/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk
También necesitaba -Iy -L: stackoverflow.com/a/52454603/895245
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
67

Esta pregunta es antigua, las otras respuestas son antiguas. La respuesta de "Empleado ruso" es muy buena e informativa, pero solo funciona si tiene el código fuente. Si no lo haces, las alternativas en ese entonces eran muy complicadas. Afortunadamente hoy en día tenemos una solución simple a este problema (como se comentó en una de sus respuestas), usando patchelf . Todo lo que tienes que hacer es:

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

Y después de eso, puedes ejecutar tu archivo:

$ ./myapp

chrootAfortunadamente, no es necesario editar manualmente los binarios. Pero recuerde hacer una copia de seguridad de su binario antes de parchearlo, si no está seguro de lo que está haciendo, porque modifica su archivo binario. Después de parcharlo, no puede restaurar la ruta anterior al intérprete / rpath. Si no funciona, tendrá que seguir parcheándolo hasta que encuentre la ruta que realmente funcionará ... Bueno, no tiene que ser un proceso de prueba y error. Por ejemplo, en el ejemplo de OP, él necesitaba GLIBC_2.3, para que pueda encontrar fácilmente qué lib proporciona esa versión usando strings:

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

En teoría, el primer grep quedaría vacío porque el sistema libc no tiene la versión que desea, y el segundo debería generar GLIBC_2.3 porque tiene la versión myapp está utilizando, por lo que sabemos que podemospatchelf usar nuestro binario con esa ruta.

Cuando intenta ejecutar un binario en Linux, el binario intenta cargar el enlazador, luego las bibliotecas, y todos deben estar en la ruta y / o en el lugar correcto. Si su problema es con el enlazador y desea averiguar qué ruta está buscando su binario, puede averiguarlo con este comando:

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

Si su problema es con las bibliotecas, los comandos que le darán las bibliotecas que se utilizan son:

$ readelf -d myapp | grep Shared
$ ldd myapp 

Esto enumerará las bibliotecas que necesita su binario, pero probablemente ya conozca las problemáticas, ya que ya están produciendo errores como en el caso de OP.

"patchelf" funciona para muchos problemas diferentes que puede encontrar al intentar ejecutar un programa, relacionados con estos 2 problemas. Por ejemplo, si obtiene:, ELF file OS ABI invalidpuede solucionarse configurando un nuevo cargador (la --set-interpreterparte del comando) como explico aquí . Otro ejemplo es el problema de obtener No such file or directorycuando ejecuta un archivo que está allí y es ejecutable, como se ejemplifica aquí . En ese caso particular, a OP le faltaba un enlace al cargador, pero tal vez en su caso no tiene acceso de root y no puede crear el enlace. Establecer un nuevo intérprete resolvería su problema.

Gracias Empleado ruso y Michael Pankov por el conocimiento y la solución!

msb
fuente
1
¡Esto fue lo más útil! Remendé binaria pitón de usar nueva glibc para tensorflow
faizan
Esta es una solución ordenada (que no conocía anteriormente patchelf), pero la frase "No es necesario ... editar binarios" puede ser un poco engañosa (ya que en realidad está editando sus binarios).
larsks
Ahí, arreglado. ;)
msb
¡Utilidad realmente útil! ¡Gracias! Aunque solo logré obtener un error de segmentación después de horas de resolver manualmente las dependencias y luego parchear todo para instalar Chrome localmente sin privilegios de administrador ...
G. Bergeron
@fgiraldeau gracias por el cumplido. :) pero la pregunta fue hecha, respondida y aceptada en 2009, no esperaría que alguien esperara 8 años antes de aceptar una respuesta. jeje; D
msb
20

Use LD_PRELOAD: coloque su biblioteca en algún lugar fuera de los directorios man lib y ejecute:

LD_PRELOAD='mylibc.so anotherlib.so' program

Ver: el artículo de Wikipedia

Flautista de Hamelín
fuente
1
pensé que sería una buena solución para un Makefile complejo, pero no funcionó para mí
galactica
eso es útil particularmente aquellos sin fuente binaria
codificador
2
um ... estaba equivocado, parece que necesito rpath the ld-linux.so to / path / to / new / lib / frist mientras compila y enlaza la fuente
codificador
1
Esto no funciona si ld - #. ##. So (desde su sistema glibc lib) no es la misma versión de glibc que libc.so. # (desde su glibc lib alternativa)
Andy
12

En primer lugar, la dependencia más importante de cada programa vinculado dinámicamente es el vinculador. Todas las bibliotecas deben coincidir con la versión del vinculador.

Tomemos un ejemplo simple: tengo el nuevo sistema ubuntu donde ejecuto algún programa (en mi caso es el compilador D - ldc2). Me gustaría ejecutarlo en el viejo CentOS, pero debido a la antigua biblioteca glibc es imposible. tengo

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)

Tengo que copiar todas las dependencias de ubuntu a centos. El método adecuado es el siguiente:

Primero, verifiquemos todas las dependencias:

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 no es una biblioteca real y no tenemos que preocuparnos por eso.

/lib64/ld-linux-x86-64.so.2 es el enlazador, que es utilizado por Linux para vincular el ejecutable con todas las bibliotecas dinámicas.

El resto de los archivos son bibliotecas reales y todos ellos junto con el enlazador deben copiarse en algún lugar de los centos.

Supongamos que todas las bibliotecas y el enlazador están en el directorio "/ mylibs".

ld-linux-x86-64.so.2, como ya he dicho, es el enlazador. No es una biblioteca dinámica sino un ejecutable estático. Puede ejecutarlo y ver que incluso tiene algunos parámetros, por ejemplo, --library-path (volveré sobre él).

En Linux, el programa vinculado dinámicamente se puede almorzar solo por su nombre, p. Ej.

/bin/ldc2

Linux carga dicho programa en la RAM y comprueba qué enlazador está configurado para ello. Por lo general, en un sistema de 64 bits, es /lib64/ld-linux-x86-64.so.2 (en su sistema de archivos es un enlace simbólico al ejecutable real). Luego, Linux ejecuta el enlazador y carga bibliotecas dinámicas.

También puedes cambiar esto un poco y hacer tal truco:

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

Es el método para obligar a Linux a usar un enlazador específico.

Y ahora podemos volver al parámetro mencionado anteriormente --library-path

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

Ejecutará ldc2 y cargará bibliotecas dinámicas desde / mylibs.

Este es el método para llamar al ejecutable con las bibliotecas elegidas (no las predeterminadas del sistema).

Arkadiusz Rychliński
fuente
Compilé un programa en RH7 y necesito que se ejecute en RH6. No quería construir un nuevo ejecutable o usar patchelf, así que esta es una gran alternativa.
Mark Rajcok
9

Configuración 1: compila tu propio glibc sin GCC dedicado y úsalo

Esta configuración podría funcionar y es rápida ya que no recompila toda la cadena de herramientas de GCC, solo glibc.

Pero no es fiable, ya que utiliza anfitrión tiempo de ejecución C objetos tales como crt1.o, crti.oy crtn.oproporcionado por glibc. Esto se menciona en: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Esos objetos realizan una configuración temprana en la que se basa Glibc, por lo que no me sorprendería si las cosas se estrellaran de maravilla y formas asombrosamente sutiles.

Para una configuración más confiable, vea la Configuración 2 a continuación.

Construya glibc e instálelo localmente:

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`

Configuración 1: verifique la compilación

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);
}

Compila y ejecuta con 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

El programa genera lo esperado:

gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674

Comando adaptado de https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location pero --sysrootfalló con:

cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install

así que lo quité

lddLa salida confirma que las lddbibliotecas y que acabamos de construir se están utilizando realmente como se esperaba:

+ 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)

El gccresultado de la depuración de compilación muestra que se usaron mis objetos de tiempo de ejecución de host, lo cual es malo como se mencionó anteriormente, pero no sé cómo solucionarlo, por ejemplo, contiene:

COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o

Configuración 1: modificar glibc

Ahora modifiquemos glibc con:

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

Luego recompile y reinstale glibc, y recompile y vuelva a ejecutar nuestro programa:

cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh

y vemos hackedimpreso algunas veces como se esperaba.

Esto confirma aún más que en realidad usamos el glibc que compilamos y no el host.

Probado en Ubuntu 18.04.

Configuración 2: configuración prístina de crosstool-NG

Esta es una alternativa a la configuración 1, y es la configuración más correcta que he logrado mucho: todo es correcto por lo que yo puedo observar, incluyendo el tiempo de ejecución C objetos tales como crt1.o, crti.oycrtn.o .

En esta configuración, compilaremos una cadena de herramientas GCC dedicada que use el glibc que queramos.

El único inconveniente de este método es que la construcción llevará más tiempo. Pero no arriesgaría una configuración de producción con nada menos.

crosstool-NG es un conjunto de scripts que descarga y compila todo de origen para nosotros, incluidos GCC, glibc y binutils.

Sí, el sistema de compilación de GCC es tan malo que necesitamos un proyecto separado para eso.

Esta configuración no es perfecta porque crosstool-NG no admite la construcción de ejecutables sin -Wlbanderas adicionales , lo que se siente extraño ya que hemos creado GCC. Pero todo parece funcionar, así que esto es solo un inconveniente.

Obtenga crosstool-NG, configúrelo y compílelo:

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`

La construcción lleva entre treinta minutos y dos horas.

La única opción de configuración obligatoria que puedo ver es hacer que coincida con la versión del núcleo del host para utilizar los encabezados del núcleo correctos. Encuentre su versión de kernel host con:

uname -a

que me muestra

4.15.0-34-generic

entonces en lo menuconfigque hago:

  • Operating System
    • Version of linux

entonces selecciono:

4.14.71

cual es la primera versión igual o anterior. Tiene que ser anterior ya que el núcleo es compatible con versiones anteriores.

Configuración 2: configuraciones opcionales

El .configque generamos con ./ct-ng x86_64-unknown-linux-gnutiene:

CT_GLIBC_V_2_27=y

Para cambiar eso, en menuconfigdo:

  • C-library
  • Version of glibc

salva el .config y continúe con la compilación.

O, si desea usar su propia fuente de glibc, por ejemplo, para usar glibc del último git, proceda de esta manera :

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: establecido en verdadero
  • C-library
    • Source of glibc
      • Custom location: decir que sí
      • Custom location
        • Custom source location: apunte a un directorio que contenga su fuente glibc

donde glibc fue clonado como:

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

Configuración 2: pruébelo

Una vez que haya creado la cadena de herramientas que desea, pruébela con:

#!/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

Todo parece funcionar como en la Configuración 1, excepto que ahora se usaron los objetos de tiempo de ejecución correctos:

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

Configuración 2: intento de recompilación glibc eficiente fallido

No parece posible con crosstool-NG, como se explica a continuación.

Si solo reconstruyes;

env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

entonces sus cambios en la ubicación de origen de glibc personalizada se tienen en cuenta, pero construye todo desde cero, por lo que es inutilizable para el desarrollo iterativo.

Si lo hacemos:

./ct-ng list-steps

da una buena visión general de los pasos de compilación:

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.

por lo tanto, vemos que hay pasos glibc entrelazados con varios pasos GCC, más notablemente libc_start_filesantescc_core_pass_2 , que es probablemente el paso más costoso junto con cc_core_pass_1.

Para compilar solo un paso, primero debe establecer la .configopción "Guardar pasos intermedios" en la compilación inicial:

  • Paths and misc options
    • Debug crosstool-NG
      • Save intermediate steps

y luego puedes probar:

env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`

pero desafortunadamente, lo +requerido como se menciona en: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

Sin embargo, tenga en cuenta que reiniciar en un paso intermedio restablece el directorio de instalación al estado que tenía durante ese paso. Es decir, tendrá una libc reconstruida, pero ningún compilador final construido con esta libc (y, por lo tanto, tampoco bibliotecas de compiladores como libstdc ++).

y, básicamente, todavía hace que la reconstrucción sea demasiado lenta para ser factible para el desarrollo, y no veo cómo superar esto sin parchear crosstool-NG.

Además, comenzar desde el libcpaso no parecía volver a copiar la fuente Custom source location, lo que hace que este método sea inutilizable.

Bono: stdlibc ++

Una ventaja adicional si también está interesado en la biblioteca estándar de C ++: ¿Cómo editar y reconstruir la fuente de la biblioteca estándar GCC libstdc ++ C ++?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
6

¿Puedes considerar usar Nix http://nixos.org/nix/ ?

Nix admite la gestión de paquetes multiusuario: varios usuarios pueden compartir una tienda Nix común de forma segura, no necesitan tener privilegios de root para instalar software y pueden instalar y usar diferentes versiones de un paquete.


fuente
4

@msb ofrece una solución segura.

Encontré este problema cuando lo hice import tensorflow as tfen un entorno conda en el CentOS 6.5que solo lo ha hecho glibc-2.12.

ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/

Quiero proporcionar algunos detalles:

Primero instale glibcen su directorio de inicio:

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

En segundo lugar, siga el mismo camino para instalar patchelf ;

Tercero, parchea tu 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

como lo menciona @msb

Ahora puedo usar tensorflow-2.0 alphaen CentOS 6.5.

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

Belter
fuente
2

No estoy seguro de que la pregunta siga siendo relevante, pero hay otra forma de solucionar el problema: Docker. Se puede instalar un contenedor casi vacío de la Distribución de origen (La distribución utilizada para el desarrollo) y copiar los archivos en el Contenedor. De esa manera, no necesita crear el sistema de archivos necesario para chroot.

usuario1396055
fuente
1

Si observa detenidamente la segunda salida, puede ver que se utiliza la nueva ubicación para las bibliotecas. Quizás todavía faltan bibliotecas que forman parte de glibc.

También creo que todas las bibliotecas utilizadas por su programa deben compilarse con esa versión de glibc. Si tiene acceso al código fuente del programa, una nueva compilación parece ser la mejor solución.

rsarro
fuente
1

"Empleado ruso" es una de las mejores respuestas, y creo que todas las demás respuestas sugeridas pueden no funcionar. La razón es simplemente porque cuando se crea una aplicación por primera vez, todas sus API que necesita se resuelven en el momento de la compilación. Usando "ldd" puede ver todas las dependencias vinculadas estáticamente:

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)

Pero en el tiempo de ejecución, Firefox también cargará muchas otras bibliotecas dinámicas, por ejemplo (para Firefox) hay muchas bibliotecas etiquetadas con "glib" cargadas (aunque no estén vinculadas estáticamente):

 /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

Muchas veces, puede ver que los nombres de una versión están vinculados a otra versión. P.ej:

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

Por lo tanto, esto significa que existen diferentes versiones de "bibliotecas" en un sistema, lo cual no es un problema ya que es el mismo archivo y proporcionará compatibilidades cuando las aplicaciones tengan dependencias de múltiples versiones.

Por lo tanto, en el nivel del sistema, todas las bibliotecas son casi interdependientes entre sí, y solo cambiar las prioridades de carga de las bibliotecas mediante la manipulación de LD_PRELOAD o LD_LIBRARY_PATH no ayudará, incluso si puede cargarse, el tiempo de ejecución puede bloquearse.

http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc

La mejor alternativa es chroot (mencionado brevemente por ER): pero para esto necesitará recrear todo el entorno en el que se ejecuta el binario original, generalmente a partir de / lib, / usr / lib /, / usr / lib / x86, etc. Puede usar "Buildroot", o YoctoProject, o simplemente alquitrán de un entorno de distribución existente. (como Fedora / Suse, etc.)

Peter Teoh
fuente
0

Cuando quería ejecutar un navegador de cromo en Ubuntu preciso (glibc-2.15), recibí el mensaje (típico) "... libc.so.6: versión 'GLIBC_2.19' no encontrada ...". Consideré el hecho de que los archivos no son necesarios de forma permanente, sino solo para comenzar. Así que recopilé los archivos necesarios para el navegador y sudo y creé un entorno mini-glibc-2.19-, inicié el navegador y luego volví a copiar los archivos originales. Los archivos necesarios están en RAM y el glibc original es el mismo.

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)

El script para ejecutar el navegador:

#!/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
dudu
fuente