Por que meu LD_LIBRARY_PATH obtém um terminal de inicialização não definido?


8

Eu tenho um script de shell para configurar algumas variáveis ​​de ambiente e iniciar qualquer programa que eu enviar como argumento:

export PATH=$HOME/local/bin:$PATH
export LD_LIBRARY_PATH=$HOME/local/lib:$LD_LIBRARY_PATH
export TESTER="MY TEST VAR"

$@

Quando eu uso isso para chamar, bashpor exemplo, ele funciona:

kjfletch@flatbed:~$ envrun.sh bash
kjfletch@flatbed:~$ echo $LD_LIBRARY_PATH
/home/kjfletch/local/lib:
kjfletch@flatbed:~$ echo $TESTER
MY TEST VAR

Quando eu usá-lo para chamar um terminal ( xterm, aterm...) a minha LD_LIBRARY_PATHfica desactivado:

kjfletch@flatbed:~$ echo $LD_LIBRARY_PATH

kjfletch@flatbed:~$ echo $TESTER

MY TEST VAR

Por que isso acontece? Como posso parar com isso? (Estou executando o Debian 5.0)

Atualizar

Meu terminal não está chamando o bash como um login:

kjfletch@flatbed:~$ echo $0
bash

Meu LD_LIBRARY_PATHnão aparece em nenhum dos arquivos de inicialização do bash (exceto .bash_history e ~ / .profile não existe.):

kjfletch@flatbed:~$ grep "LD" ~/.bash*
kjfletch@flatbed:~$ grep "LD" /etc/bash.bashrc 
kjfletch@flatbed:~$ grep "LD" /etc/profile 

Algum desses arquivos de inicialização está chamando o comando "source" ou o "." comando para trazer outros scripts de inicialização? Nesse caso, um deles pode ser o culpado.
22610 Kevin Panko

Não responder à sua pergunta, mas a realmente bom seria se livrar da necessidade de LD_LIBRARY_PATH (razões: 1 2 3 ). Você pode, por exemplo, editar o /etc/ld.so.conf ou compilar quaisquer libs definidas pelo usuário que você possua no ~ / local de uma maneira que eles saibam onde encontrar suas bibliotecas (veja os links que eu forneci).
DevSolar

Respostas:


9

O binário terminal é mais provável setgidde agrupar utmp. Binários setuid e setgid desativados LD_LIBRARY_PATHpor motivos de segurança; veja ld.so(8):

As bibliotecas compartilhadas necessárias, necessárias ao programa, são pesquisadas na seguinte ordem

  • Usando a variável de ambiente LD_LIBRARY_PATH( LD_AOUT_LIBRARY_PATHpara programas a.out). Exceto se o executável for um binário setuid / setgid, nesse caso, será ignorado.

4

No terminal (xterm, aterm etc), verifique como o shell foi chamado: Um shell de login mostrará "-bash" e um shell que não seja de login mostrará "bash" quando você ligar echo $0.

$ echo $0
-bash
$ bash
$ echo $0
bash

Um shell bash de login lerá o seguinte na ordem:

  1. / etc / profile
  2. ~ / .bash_profile
  3. ~ / .bash_login
  4. ~ / .profile

Verifique se algum desses arquivos existe e se eles redefinem a variável. Você também precisará seguir os arquivos que esses arquivos incluem.

Se o bash não for chamado como um shell de logon, ele ainda lerá os arquivos abaixo se for determinado como um shell interativo.

  1. /etc/bash.bashrc
  2. ~ / .bashrc

Uma maneira simples de determinar o tipo de shell bash que está sendo chamado é definir seu .bash_profile e .bashrc e ecoar "Login shell" e "Shell interativo", respectivamente.

Depois de saber o tipo de shell que está sendo chamado, você tem a opção de adicionar seu script ao arquivo .bashrc ou .bash_profile em seu diretório pessoal. Como alternativa, você pode desativar a redefinição do LD_LIBRARY_PATH.

Observe que, se o seu .bashrc ou .bash_profile estiver protegido por uma proteção semelhante à abaixo, talvez seja necessário chamar seu script fora dele:

if [ "X$BASH_SOURCED" != "XYES" ]; then
        export BASH_SOURCED=YES

fi

Esses guardas são normalmente colocados para impedir que um script seja originado várias vezes em uma sessão.

Editar: se estiver provando que o tedius rastreará onde a variável está sendo redefinida e você tiver acesso a / etc / profile ou /etc/bash.bashrc, por exemplo, poderá adicionar temporariamente "set -x" na parte superior do script para ver todos os comandos que são executados. A saída será bem detalhada, primeiro faça um "set -x" em seu shell e execute alguns comandos para que você saiba o que esperar.


+1 Obrigado pela informação. Atualizei meu OP em resposta à sua resposta.
kjfletch

Você vê o mesmo comportamento se inserir um novo shell bash no mesmo terminal digitando bash? Aliás, você também precisará verificar os arquivos chamados em /etc/bash.bashrc e / etc / profile - um deles pode desmarcar a variável. Como alternativa, use a set -xopção debug para obter um despejo de tudo o que é feito a partir do momento em que o shell é criado.

O set -xdespejo não faz referência a LD_LIBRARY_PATH. Fantasma desabilitado.
kjfletch

4

O bash usará scripts de inicialização diferentes, dependendo de como é iniciado. Existem sete maneiras diferentes de iniciá-lo, mas as mais importantes são shells de login versus shells interativos que não são de login.

Confira o manual do bash para mais detalhes. Eu suspeitaria que o / etc / profile ou o ~ / .bash_profile esteja fazendo algo para redefinir a variável LD_LIBRARY_PATH.


Editar: Eu acho que você fez tudo o que pode para mostrar que o bash não possui nenhum script de inicialização que desative LD_LIBRARY_PATH. É hora de trazer as grandes armas.

O comando a seguir exibirá o ambiente inteiro à medida que cada processo é iniciado, do bash ao xterm e qualquer outra coisa envolvida - você provavelmente obterá uma grande quantidade de resultados, portanto, salvar a saída em um arquivo é uma boa ideia .

strace -v -f -e trace=process -o strace_output.txt envrun.sh xterm

Agora, o arquivo strace_output.txt mostrará cada chamada do sistema feita pelo seu script e cada processo filho, e você poderá ver qual processo foi o último a ter LD_LIBRARY_PATH antes de ser removido.


2

(Esta pergunta é muito antiga, mas acabei de encontrar o mesmo problema e estou documentando a solução para posterioridade :)

Eu tive esse problema com a tela GNU (o multiplexador de terminal), mas também pode acontecer com um terminal comum. Teddy estava certo no meu caso, a tela definiu um conjunto de guias.

$ ls -l /usr/bin/screen
-rwxr-sr-x 1 root 84 361016 Mar 30  2011 /usr/bin/screen
      ^

Minha solução foi salvar LD_LIBRARY_PATH antes da execução e restaurá-lo posteriormente. Então, criei um wrapper ~ / bin / screen (coloque ~ / bin em PATH), com o seguinte conteúdo:

#!/bin/bash

# somehow, screen resets LD_LIBRARY_PATH.
# save it here, and restore it in .bashrc
export PRESERVE_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
/usr/bin/screen "$@"

e, em seguida, tornou executável com chmod +x ~/bin/screen. Pode ser necessário abrir um novo shell para que ele pegue o invólucro.

Em seguida, adicionei o seguinte ao ~ / .bashrc. Lembre-se de que o ~ / .bashrc é originado toda vez que você inicia o bash, ao contrário do ~ / .bash_profile, que somente é originado no login (geralmente na inicialização ou quando você faz login no ssh).

if [[ "$PRESERVE_LD_LIBRARY_PATH" != "" ]]; then
    export LD_LIBRARY_PATH="$PRESERVE_LD_LIBRARY_PATH"
    #echo "restored LD_LIBRARY_PATH"
    export -n PRESERVE_LD_LIBRARY_PATH
fi

Agora a tela (ou aterm, xterm, ... apenas substitua-a acima) deve preservar $ LD_LIBRARY_PATH como desejado.


Você também pode restaurar LD_LIBRARY_PATHem .screenrc( em vez de .bashrc): setenv LD_LIBRARY_PATH "$PRESERVE_LD_LIBRARY_PATH"seguido porunsetenv PRESERVE_LD_LIBRARY_PATH
nandhp

0

Parece que você tem algum arquivo .bashrc (ou equivalente) em seu diretório pessoal que define essa variável. Eu não sei muito mais detalhes embora.

Editar Ok, desde que o bash funciona, acho que não o .bashrc. Mas talvez algum outro arquivo de configuração seja executado da mesma maneira, quando você inicia o xterm ou o aterm.


Este foi o meu pensamento original. Depois de muita pesquisa, não há nada a ser encontrado. Tenho o benefício de ter um $ HOME muito limpo (NOVO).
kjfletch

0

A maioria dos sistemas de janelas recriar o processo de login quando eles iniciam uma janela do terminal, principalmente porque a janela do terminal se torna filho do gerenciador de janelas e não o shell de inicialização.

Portanto, coloque-o em seu .bash_profile ou .bashrc, se desejar que ele apareça em uma nova janela.

Outra alternativa é entregar ao xterm (por exemplo) um argumento para executar um script de inicialização. Não saia no final desse script ....


Vou ter que recorrer a isso, eu acho. Provavelmente irei originar minhas variáveis ​​de ambiente em ambos .xinitrc para que meu gerenciador de janelas os tenha e em .bashrc para que minhas janelas de terminal os tenham.
kjfletch
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.