
Acabei de baixar um tar
arquivo que supostamente inclui tudo o que é necessário para executar um programa que podemos chamar de some_binary
. Extraí seu conteúdo e vejo o seguinte:
- Um binário (vamos chamá-lo
some_binary
) - Uma
lib
pasta com várias bibliotecas dinâmicas (arquivos .so), como/lib/ld-linux-x86-64.so
- e um script de shell chamado
some_binary.sh
O script possui o seguinte conteúdo:
#!/bin/bash
`dirname "$0"`/lib/ld-linux-x86-64.so.2 `dirname "$0"`/some_binary "$@"
e executá-lo como ./some_binary.sh some arguments
parece funcionar ./some_binary
corretamente. Curiosamente, executando o seguinte script:
#!/bin/bash
LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
./some_binary "$@"
como ./my_script.sh some arguments
não funciona. Isso resulta em erros de realocação (símbolos indefinidos), provavelmente devido ao carregamento incorreto das bibliotecas em./lib
Além disso, executar as duas instruções a seguir na linha de comando resulta em segmentation fault
:
> LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
> ./some_binary some arguments
Com isso, minhas perguntas são:
- O que o primeiro script faz?
- Por que obtenho resultados diferentes nessas três tentativas? e por que não posso simplesmente adicionar
$pwd/lib
eLD_LIBRARY_PATH
executarsome_binary
diretamente?
Responder1
O programa vem com seu própriocarregador dinâmico. É muito raro que os programas precisem de seu próprio carregador dinâmico: normalmente o que está no seu sistema também funcionará. Isto pode ser necessário se o programa foi vinculado a uma biblioteca padrão diferente da GNU libc ou se foi vinculado a uma GNU libc compilada com configurações estranhas.
Pode ser suficiente informar ao carregador onde encontrar as bibliotecas preferidas do programa. Sua tentativa quase faz isso, mas não exatamente. Se LD_LIBRARY_PATH
ainda não estiver no ambiente, a atribuição LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
definirá apenas uma variável de shell, não uma variável de ambiente, para que o programa não veja nada. Além disso, $CWD
geralmente se expande para uma string vazia, provavelmente você quis dizer $PWD
ou melhor $(dirname "$0")
(ou seja, o diretório que contém o script). Cuidado também com o fato de você ter usado lib
e LIB
inconsistentemente em sua pergunta. Tentar
#!/bin/sh
export LD_LIBRARY_PATH="$(dirname "$0")/lib:$LD_LIBRARY_PATH"
exec "$(dirname "$0")/some_binary" "$@"
ou melhor, para evitar ter uma entrada vazia no final LD_LIBRARY_PATH
se não tiver sido definida antes (isso pode ser ruim porque uma entrada vazia representa o diretório atual, embora no final do caminho só seja prejudicial se uma biblioteca estiver ' não encontrei onde deveria 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" "$@"