
Ich habe gerade eine tar
Datei heruntergeladen, die alles enthalten soll, was zum Ausführen eines Programms erforderlich ist, das wir aufrufen können some_binary
. Ich habe den Inhalt extrahiert und sehe Folgendes:
- Eine Binärdatei (nennen wir sie
some_binary
) - Ein
lib
Ordner mit verschiedenen dynamischen Bibliotheken (.so-Dateien) wie/lib/ld-linux-x86-64.so
- und ein Shell-Skript namens
some_binary.sh
Das Skript hat folgenden Inhalt:
#!/bin/bash
`dirname "$0"`/lib/ld-linux-x86-64.so.2 `dirname "$0"`/some_binary "$@"
und es ./some_binary.sh some arguments
scheint korrekt zu laufen ./some_binary
. Seltsamerweise funktioniert es, wenn man das folgende Skript ausführt:
#!/bin/bash
LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
./some_binary "$@"
as ./my_script.sh some arguments
funktioniert nicht. Es kommt zu Verschiebungsfehlern (undefinierte Symbole), vermutlich durch falsches Laden der Bibliotheken unter./lib
Darüber hinaus führt das Ausführen der folgenden beiden Anweisungen von der Befehlszeile zu segmentation fault
:
> LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
> ./some_binary some arguments
Vor diesem Hintergrund sind meine Fragen:
- Was macht das erste Skript?
- Warum erhalte ich bei diesen drei Versuchen unterschiedliche Ergebnisse? Und warum kann ich nicht einfach hinzufügen
$pwd/lib
undLD_LIBRARY_PATH
dannsome_binary
direkt ausführen?
Antwort1
Das Programm verfügt über eine eigenedynamischer Lader. Es kommt nur selten vor, dass Programme einen eigenen dynamischen Loader benötigen: Normalerweise funktioniert der auf Ihrem System vorhandene auch. Dies kann notwendig sein, wenn das Programm mit einer anderen Standardbibliothek als GNU libc verknüpft wurde oder wenn es mit einer GNU libc verknüpft wurde, die mit seltsamen Einstellungen kompiliert wurde.
Es kann ausreichen, dem Loader mitzuteilen, wo die bevorzugten Bibliotheken des Programms zu finden sind. Ihr Versuch schafft das fast, aber nicht ganz. Wenn LD_LIBRARY_PATH
nicht bereits in der Umgebung vorhanden ist, LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
definiert die Zuweisung nur eine Shell-Variable, keine Umgebungsvariable, sodass das Programm nichts sieht. Außerdem $CWD
wird normalerweise zu der leeren Zeichenfolge erweitert, die Sie wahrscheinlich meinten, $PWD
oder besser $(dirname "$0")
(also das Verzeichnis, das das Skript enthält). Beachten Sie auch, dass Sie in Ihrer Frage lib
und inkonsistent verwendet haben. Versuchen SieLIB
#!/bin/sh
export LD_LIBRARY_PATH="$(dirname "$0")/lib:$LD_LIBRARY_PATH"
exec "$(dirname "$0")/some_binary" "$@"
oder besser, um einen leeren Eintrag am Ende zu vermeiden, LD_LIBRARY_PATH
wenn dieser nicht vorher definiert wurde (das kann schlecht sein, weil ein leerer Eintrag für das aktuelle Verzeichnis steht, am Ende des Pfads ist es jedoch nur dann schädlich, wenn eine Bibliothek nicht dort gefunden wird, wo sie sein sollte):
#!/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" "$@"