Apple Mavericks - por que este script BASH de uma linha não define meu ambiente virtual Python como esperado?

2

Eu tenho o seguinte script Bash:

#!/bin/bash
echo $MYPROJECT_HOME/bin/myproject_venv/bin/activate
source $MYPROJECT_HOME/bin/myproject_venv/bin/activate
echo $MYPROJECT_HOME/bin/myproject_venv/bin/activate

As permissões mostram que o arquivo é executável e é de minha propriedade. As permissões são:

-rwxr-xr-x

Quando executo o script na linha de comando, ele imprime duas vezes o caminho correto para o script activate , como esperado. No entanto, ele não executa corretamente a linha do meio - aquela que origina o script.

Se eu copiar a linha do meio e executá-la na linha de comando, ela funcionará bem.

O que dá?

    
por jononomo 25.11.2013 / 18:34

2 respostas

4

O problema

Ele está funcionando perfeitamente (você pode verificar isso adicionando um comando echo ao arquivo originado), o problema é que ele é executado em um shell diferente. Quando você executa um script de shell (usando o bash como exemplo, mas as mesmas ideias se aplicam a outros shells), ele inicia um shell não-login e não interativo para ser executado. Isso significa que uma mini instância separada de bash é lançada. e que bash é o que origina seu script. É por isso que as variáveis que você está configurando não estão presentes no shell pai.

Você pode testar isso com bastante facilidade:

$ cat test.sh
#!/bin/bash
export FOO="bar"
echo "FOO in test.sh is : $FOO"

$ export FOO="OOF"
$ echo $FOO
OOF                       ### Here, in the parent shell, $FOO is 'OOF'
$ ./test.sh
FOO in test.sh is : bar   ### In the shell running the script, $FOO is 'bar'
$ echo $FOO
OOF                       ### Back in the parent shell, $FOO is still 'OOF'

Portanto, os scripts de shell são executados em seu próprio shell separado e, conforme declarado em help source :

source: source filename [arguments]
    Execute commands from a file in the current shell.

Portanto, source afeta apenas o shell atual que, no caso de um script bash, é o que foi iniciado para executar o script em si e não o shell pai em que você digitou o nome do script.

Soluções

Se quiser criar um arquivo que defina variáveis, você deve fazer isso a partir do shell em que está executando, apenas execute o comando source diretamente.

Como alternativa, você pode ter o source para todas as novas instâncias do shell adicionando-o ao arquivo de inicialização bash . Isso é .profile no OSX e .bashrc na maioria dos outros casos. Então, edite seu arquivo $HOME/.profile e adicione esta linha:

source $MYPROJECT_HOME/bin/myproject_venv/bin/activate

Agora, todos os novos terminais que você abrir terão como fonte o arquivo activate . Ou, se você quiser fazer isso sob demanda, transforme seu script em uma função. Adicione estas linhas ao seu .profile :

activate(){
  echo "Sourcing $TEST/activate"
  source $TEST/activate
}

As funções, ao contrário dos scripts, não iniciam uma nova instância do shell e, portanto, podem modificar o shell do qual você as inicia. Agora você pode executar activate para originar o arquivo $TEST/activate .

    
por 26.11.2013 / 00:32
2

Pode ser que o script activate esteja em execução, mas funciona definindo variáveis de ambiente? Se assim for, isso pode lhe dar problemas. Como teste, criei dois scripts, command e activate . O primeiro é como o seu script Bash:

#!/bin/bash
echo $TEST/activate
source $TEST/activate
echo $TEST/activate

e activate é um simples marcador:

export TEST="Hello World!"

A saída mostra que as alterações nas variáveis de ambiente não são retidas. Aqui estão os comandos que usei para executar isso e os resultados:

export TEST="/Users/me"
./command

Isso parece mudar variáveis de ambiente; aqui está a saída:

/Users/me/activate
Hello World!/activate

Mas no meu prompt de comando, posso ver que o valor de $ TEST é o mesmo de antes:

echo $TEST

tem a saída:

/Users/me

Talvez este seja o seu problema?

    
por 25.11.2013 / 19:30