como exportar VARs de um subshell para um shell pai?

10

Eu tenho um script de shell Korn

#!/bin/ksh
# set the right ENV
case $INPUT in
abc)
  export BIN=${ABC_BIN}
  ;;
  def)
  export BIN=${DEF_BIN}
  ;;
  *)
  export BIN=${BASE_BIN}
  ;;
esac
# exit 0 <- bad idea for sourcing the file

agora esses VARs são exportados apenas em um subshell, mas eu quero que eles sejam definidos no meu shell pai também; portanto, quando estou no prompt, esses vars ainda estão definidos corretamente.

Eu sei sobre

. .myscript.sh

mas existe uma maneira de fazer isso sem 'terceirizar'? como meus usuários frequentemente esquecem de 'fonte'.


EDIT1: removendo a parte "exit 0" - era só eu digitando sem pensar primeiro

EDIT2: para adicionar mais detalhes sobre por que eu preciso disso: meus desenvolvedores escrevem código para (por uma questão de simplicidade) 2 aplicativos: ABC e DEF. cada aplicativo é executado em produção por usuários separados usrabc e usrdef; portanto, eles configuraram seus $ BIN, $ CFG, $ ORA_HOME, o que for - específico para seus aplicativos.

tão

  • $ BIN do ABC = / opt / abc / bin # $ ABC_BIN no script acima
  • $ BIN do DEF = / opt / def / bin # $ DEF_BIN

etc.

agora, na caixa de desenvolvimento, os desenvolvedores podem desenvolver o ABC e o DEF ao mesmo tempo em sua própria conta de usuário 'justin_case', e eu os faço originar o arquivo (acima) para que eles possam alternar suas configurações de ENV var. ($ BIN deve apontar para $ ABC_BIN de uma só vez e, em seguida, preciso mudar para $ BIN = $ DEF_BIN)

agora, o script também deve criar novas caixas de proteção para o desenvolvimento paralelo do mesmo aplicativo etc. Isso me faz fazê-lo interativamente, solicitando o nome da caixa de proteção etc.

  • / home / justin_case / sandbox_abc_beta2
  • / home / justin_case / sandbox_abc_r1
  • / home / justin_case / sandbox_def_r1

a outra opção que considerei é escrever aliases e adicioná-los ao perfil de todos os usuários

  • alias 'setup_env =. .myscript.sh '

e execute-o com

  • setup_env parameter1 ... parameterX

isso faz mais sentido para mim agora

webwesen
fonte
Sim - você pode fazer isso com um apelido ou função (eu prefiro funções) onde você tem a função prod () {export VAR = snoopy; }; e a função dev () {export VAR = woodstock; };
chris

Respostas:

11

Eu acho que é um tipo de problema "não posso fazer" ...

Primeiro - você não gostaria de obter esse script por causa da saída 0 no final.

Segundo, nenhum processo filho unix pode alterar diretamente o ambiente do pai. Caso contrário, todos os tipos de coisas loucas seriam possíveis.

Você poderia adicionar algo ao ambiente deles com o perfil padrão ou os arquivos bashrc, ou escrever um wrapper para qualquer programa que eles estejam tentando executar?

Permitam-me elaborar o conceito de "invólucro".

Digamos que você queira executar o programa snoopy com PROD ou DEV na variável de ambiente "OPTIONS", dependendo se você deseja produção ou desenvolvimento. Se não estiver definido, digamos que o Snoopy faça algo doido como acabar com o banco de dados para produção e desenvolvimento ...

renomeie "snoopy" para snoopy.bin (ou .snoopy.bin)

em seguida, coloque um script no mesmo local chamado "snoopy" que contém este:

#!/bin/sh

export OPTIONS

case "$OPTIONS" 
in
  PROD) ;;
  DEV) ;;
  *) OPTIONS=DEV ;;
esac

#the binary is actually named snoopy.bin 

exec "$0.bin" "$@"

Se você não quiser mexer no arquivo real, coloque esse script em algum lugar do sistema de arquivos que estará à frente do programa snoopy real no PATH do usuário e tenha um caminho completo para o binário na instrução exec do script ...

chris
fonte
5

A resposta é sourcing. O fornecimento permite incluir variáveis ​​em um script no shell atual , mas nunca um dos pais. É verdade, você deve ter cuidado para não usar nenhum comando de saída ou similar, pois isso fecharia seu shell atual.

Você pode obter um script usando o ".", Ou seja,

. ./myscript.ksh

txwikinger
fonte
3

Talvez se você tentar ...

#!/bin/bash

mknod fifo p

(
       echo 'value' > fifo &
)

VARIABLE=`cat fifo`
rm fifo

Não é exatamente uma exportação variável, mas pode fornecer comunicação básica com o processo pai.

Oscar
fonte
1

OK, não ria agora. Solução muito rápida e muito suja é adicionar

echo "Please copy and paste this command:"
echo ""
echo "export BIN=\"$BIN\""

ao seu script.

Outra abordagem . Apenas execum $ SHELL subordinado em seu script, talvez com um prompt diferente (altere $ PS1 para notificar os usuários em que ambiente eles estão trabalhando para reduzir a confusão).

Outra abordagem (a minha favorita). Os usuários esquecem de obter seu script, por que isso? O fornecimento é precisamente o caminho padrão a seguir. Talvez uma boa maneira de lembrá-los seja remover a primeira linha ( #!/bin/sh) e depois chmod a-xa linha. Ainda pode ser obtido depois disso, mas obviamente não pode ser executado por engano.

Rant : Em suma , sinto que você teve uma ideia estranha em primeiro lugar. Talvez não seja estranho ... Eu diria um pouco não-Unix em grande estilo. Eu nunca precisei exportar ambiente para pai na minha vida. Vi uma vez uma situação semelhante - login .profile perguntando qual dos três ambientes diferentes definir para uma única conta Oracle. Má ideia: no final, os usuários preferiram migrar para o sudo (eles usaram três contas oraxxx diferentes). O que você está tentando alcançar, se posso perguntar?

kubanczyk
fonte