Bash: por que o “set” não está se comportando como eu esperava?

1

Eu observei que apenas os valores das variáveis exportadas são anexados à variável my PATH através do meu Mac OS X .bash_profile. Considerando que, os valores das variáveis definidas localmente não podem. Por que as variáveis locais não podem ser anexadas ao caminho?

“Você interpretou mal alguma coisa, mas o que? Poste o código que confunde você. - Gilles ontem ”

Por favor, considere este trecho, onde eu defino a variável MONGODB como:

set MONGODB="/usr/local/mongodb/bin"    
export PATH=${PATH}:${MONGODB}

Eu fonte .bash_profile no terminal. Eu vejo o seguinte eco ...

CAMINHO = ~ / bin: / usr / bin: / usr / local / bin: / usr / local / sbin:

Considerando que, se eu exportar o MONGODB, e fonte o meu .bash_profile, eu vejo o seguinte eco ...

CAMINHO = ~ / bin: / usr / bin: / usr / local / bin: / usr / local / sbin: / usr / local / mongodb / bin

Talvez o uso de "set" seja impróprio?

    
por seasonedgeek 14.03.2011 / 22:40

3 respostas

3
set MONGODB="/usr/local/mongodb/bin"

Esta não é uma atribuição de variável. (É um em shell C (csh, tcsh), mas não em shells no estilo Bourne (sh, ash, bash, ksh, zsh,…).) Essa é uma chamada para o set integrado, que define os parâmetros posicionais, ou seja, $1 , $2 , etc. Tente executar este comando em um terminal e, em seguida, echo $1 .

Para atribuir um valor a uma variável shell, basta escrever

MONGODB="/usr/local/mongodb/bin"

Isso cria uma variável de shell (também chamada de parâmetro (nomeado)), que você pode acessar com $MONGODB . A variável permanece interna no shell, a menos que você tenha exportado com export MONGODB . Se exportada, a variável também é visível para todos os processos iniciados por esse shell, através do ambiente . Você pode condensar a atribuição e a exportação em uma única linha:

export MONGODB="/usr/local/mongodb/bin"

Para o que você está fazendo, não parece haver necessidade de MONGODB fora do script e PATH já foi exportado (uma vez que uma variável é exportada, se você atribuir um novo valor, ela é refletido no meio ambiente). Então você pode escrever:

MONGODB="/usr/local/mongodb/bin"    
PATH=${PATH}:${MONGODB}
    
por 16.03.2011 / 00:34
2

Tentarei explicar como as variáveis do shell funcionam. É absolutamente possível acrescentar variáveis locais a uma variável de ambiente como o PATH.

Todo processo em execução possui uma lista de variáveis de ambiente. Eles são pares nome = valor. Quando um novo processo é criado com fork () ele herda essas variáveis (entre outras coisas, como arquivos abertos, id de usuário , etc). Em contraste, as variáveis de shell são um conceito de shell interno. Eles não são herdados ao criar um novo processo. Você pode exportar variáveis de shell e torná-las variáveis de ambiente. Quando em um script de shell, você escreve FOO='bar' , que é uma variável do shell. Você pode tentar criar dois scripts:

# test1.sh
FOO='bar'
sh test2.sh

# test2.sh
echo "${FOO}"

Quando você executa o primeiro script, ele define uma variável de shell interna e chama fork (). O processo de shell pai será wait () para que o filho termine e a execução continue (se houver mais comandos) . No processo filho exec () é chamado para carregar um novo shell. Este novo processo não sabe sobre o FOO. Se você modificar o primeiro script:

# test1.sh
export FOO='bar'
sh test2.sh

a variável FOO se torna parte do ambiente e herdada do processo bifurcado. É importante observar que o ambiente não é global. Processos filhos não podem afetar as variáveis de ambiente de seus pais.

# test3.sh
sh test4.sh
echo "${PATH}"

# test4.sh
export PATH="${PATH}:/new/path"

As modificações no test4.sh não são visíveis no test3.sh. A informação simplesmente não é assim. Quando o processo filho termina, seu ambiente é descartado. Vamos mudar o test3.sh:

# test3.sh
source test4.sh
echo "${PATH}"

Source é um comando shell embutido. Ele diz ao shell para abrir um arquivo e ler e executar seu conteúdo. Existe apenas um único processo de shell. Dessa forma, o chamador pode ver as modificações nas variáveis de ambiente e até nas variáveis do shell.

Como você provavelmente sabe, o PATH é uma variável de ambiente especial que informa ao shell onde procurar outros executáveis. Quando um novo shell de login é iniciado, ele automaticamente origina .bash_profile. As variáveis declaradas lá serão visíveis. No entanto, se no .bash_profile você chamar outros scripts com sh, o PATH que você definiu nesses scripts será perdido.

    
por 15.03.2011 / 12:49
1

Perhaps, using "set" is improper?

Sim, existe o seu problema. set não faz o que você poderia esperar. A partir da documentação :

This builtin is so complicated that it deserves its own section. set allows you to change the values of shell options and set the positional parameters, or to display the names and values of shell variables.

Observe a notável falta de "variáveis de shell realmente definidas" nessa lista de coisas que ela faz. Enterrado em todos os docs, você verá que o que ele está fazendo é definir os parâmetros posicionais do shell para os argumentos que você deu. Você está apenas dando um argumento, todo MONGODB="/usr/local/mongodb/bin" . Portanto, $1 é definido para isso (e $# é definido como 1, pois há apenas um argumento).

Marque um para nomes de comandos Unix anti-mnemônicos, hein?

De qualquer forma, tente apenas:

MONGODB=/usr/local/mongodb/bin
export PATH=${PATH}:${MONGODB}

e funcionará.

    
por 16.03.2011 / 00:32

Tags