
Acabo de descargar un tar
archivo que se supone incluye todo lo necesario para ejecutar un programa al que podemos llamar some_binary
. Extraje su contenido y veo lo siguiente:
- Un binario (llamémoslo
some_binary
) - Una
lib
carpeta con varias bibliotecas dinámicas (archivos .so) como/lib/ld-linux-x86-64.so
- y un script de shell llamado
some_binary.sh
El guión tiene el siguiente contenido:
#!/bin/bash
`dirname "$0"`/lib/ld-linux-x86-64.so.2 `dirname "$0"`/some_binary "$@"
y ejecutarlo como ./some_binary.sh some arguments
parece funcionar ./some_binary
correctamente. Por extraño que parezca, ejecuta el siguiente script:
#!/bin/bash
LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
./some_binary "$@"
como ./my_script.sh some arguments
no funciona. Da como resultado errores de reubicación (símbolos indefinidos), presumiblemente por cargar incorrectamente las bibliotecas en./lib
Además, ejecutar las dos declaraciones siguientes desde la línea de comando da como resultado segmentation fault
:
> LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
> ./some_binary some arguments
Con esto, mis preguntas son:
- ¿Qué hace el primer guión?
- ¿Por qué obtengo resultados diferentes en estos tres intentos? ¿Y por qué no puedo simplemente agregar
$pwd/lib
yLD_LIBRARY_PATH
luego ejecutarsome_binary
directamente?
Respuesta1
El programa viene con su propiocargador dinámico. Es bastante raro que los programas necesiten su propio cargador dinámico: normalmente el de su sistema también funcionará. Esto puede ser necesario si el programa se vinculó a una biblioteca estándar que no sea GNU libc o si se vinculó a una libc GNU compilada con configuraciones extrañas.
Puede ser suficiente decirle al cargador dónde encontrar las bibliotecas preferidas del programa. Tu intento casi logra eso, pero no del todo. Si LD_LIBRARY_PATH
aún no está en el entorno, entonces la asignación LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
solo define una variable de shell, no una variable de entorno, por lo que el programa no ve nada. Además, $CWD
generalmente se expande a la cadena vacía, probablemente quiso decir $PWD
o mejor $(dirname "$0")
(es decir, el directorio que contiene el script). También tenga en cuenta que utilizó lib
y LIB
de manera inconsistente en su pregunta. Intentar
#!/bin/sh
export LD_LIBRARY_PATH="$(dirname "$0")/lib:$LD_LIBRARY_PATH"
exec "$(dirname "$0")/some_binary" "$@"
o mejor, para evitar tener una entrada vacía al final LD_LIBRARY_PATH
si no se definió antes (esto puede ser malo porque una entrada vacía representa el directorio actual, aunque al final de la ruta solo es perjudicial si hay una biblioteca). No se encuentra donde debería estar):
#!/bin/sh
export LD_LIBRARY_PATH="$(dirname "$0")/lib:$LD_LIBRARY_PATH"
case "$LD_LIBRARY_PATH" in *:) LD_LIBRARY_PATH=${LD_LIBRARY_PATH%:};; esac
exec "$(dirname "$0")/some_binary" "$@"