ver check linux gcc glibc

linux - check - Varias bibliotecas glibc en un solo host



glibc version centos (7)

Varias 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 enlazando a / lib y no retomando desde donde los puse?

Gracias


"Ruso empleado" es una de las mejores respuestas, y creo que todas las otras respuestas sugeridas pueden no funcionar. El motivo es simplemente porque cuando se crea una aplicación por primera vez, todas las API que necesita se resuelven en tiempo de compilación. Usando "ldd" puedes ver todas las dependencias enlazadas 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 tiempo de ejecución, Firefox también cargará muchas otras bibliotecas dinámicas, por ejemplo (para Firefox) hay muchas bibliotecas "glib" cargadas (aunque estáticamente vinculado no hay ninguna):

/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 los nombres de una versión enlazada en 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 existe una versión diferente 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, a nivel del sistema, todas las bibliotecas son casi interdependientes entre sí, y simplemente cambiar la prioridad de carga de las bibliotecas mediante la manipulación de LD_PRELOAD o LD_LIBRARY_PATH no ayudará, incluso si se puede cargar, el tiempo de ejecución aún puede bloquearse.

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

La mejor alternativa es chroot (mencionada brevemente por ER): pero para esto deberá recrear todo el entorno en el que se encuentra la ejecución binaria original, generalmente a partir de / lib, / usr / lib /, / usr / lib / x86, etc. Puede usar "Buildroot" o YoctoProject, o simplemente tar de un entorno Distro existente. (como Fedora / Suse, etc.)


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

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


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

Tomemos un exaple simple: tengo el sistema newset 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 biblioteca anterior de 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, revisemos 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 nos tiene que importar.

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

El resto de los archivos son bibliotecas reales y todos ellos junto con el vinculador 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 ejecutable estático. Puede ejecutarlo y ver que incluso tenga algunos parámetros, por ejemplo, --library-path (volveré a él).

En Linux, el programa vinculado dinámicamente se puede alternar solo por su nombre, por ejemplo

/bin/ldc2

Linux carga dicho programa en la memoria RAM y verifica qué enlazador está configurado. Por lo general, en el 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 las bibliotecas dinámicas.

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

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

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

Y ahora podemos volver al parámetro anterior mencionado --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 bibliotecas elegidas (no predeterminadas por el sistema).


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 de forma rígida 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 archivo 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 opción -rpath linker hará que el cargador de tiempo de ejecución busque bibliotecas en /path/to/newglibc (para que no tenga que establecer LD_LIBRARY_PATH antes de ejecutarlo), y la opción -dynamic-linker "cocerá" la ruta para corregir ld-linux.so.2 en la aplicación.

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


Esta pregunta es vieja, las otras respuestas son viejas. La respuesta del ruso empleado es muy buena e informativa, pero solo funciona si tienes el código fuente. Si no lo hace, las alternativas en aquel entonces fueron muy difíciles. Afortunadamente hoy en día tenemos una solución simple a este problema (como se comentó en una de sus respuestas), usando nixos.org/patchelf.html . 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 simplemente ejecutar tu archivo:

$ ./myapp

No hay necesidad de chroot o editar binarios manualmente, afortunadamente. Pero recuerde hacer una copia de seguridad de su binario antes de aplicarle un parche, si no está seguro de lo que está haciendo, porque modifica su archivo binario. Después de parchearlo, no puede restaurar la ruta anterior a interpreter / rpath. Si no funciona, tendrás que seguir parchándolo hasta que encuentres la ruta que realmente funcionará ... Bueno, no tiene que ser un proceso de prueba y error. Por ejemplo, en el ejemplo de OP, necesitaba GLIBC_2.3 , por lo que puede 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 vendría vacío porque el sistema libc no tiene la versión que él quiere, y el segundo debe producir GLIBC_2.3 porque tiene la versión que myapp está usando, entonces sabemos que podemos patchelf nuestro binario usando ese camino.

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 librerías, los comandos que le darán las librerías que se usan son:

$ readelf -d myapp | grep Shared $ ldd myapp

Esto mostrará una lista de las bibliotecas que necesita su sistema binario, pero probablemente ya conozca las problemáticas, dado que ya están generando errores como en el caso de OP.

"patchelf" funciona para muchos problemas diferentes que puede encontrar al intentar ejecutar un programa, relacionado con estos 2 problemas. Por ejemplo, si obtiene: ELF file OS ABI invalid , se puede solucionar estableciendo un nuevo cargador (la parte del --set-interpreter de comandos del comando) como explico here . Otro ejemplo es el problema de obtener No such file or directory cuando ejecuta un archivo que está allí y ejecutable, como se ejemplifica here . En ese caso particular, a OP le faltaba un enlace al cargador, pero tal vez en su caso no tenga acceso de administrador y no pueda crear el enlace. Establecer un nuevo intérprete resolvería su problema.

¡Gracias Russian y Michael Pankov por la información y la solución!


Si observa detenidamente el segundo resultado, puede ver que se usa la nueva ubicación para las bibliotecas. Tal vez todavía faltan bibliotecas que son parte de glibc.

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


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