Digamos que eu tenho um script shell / bash nomeado test.sh
com:
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
Minha test2.sh
aparência é assim:
#!/bin/bash
echo ${TESTVARIABLE}
Isso não funciona. Eu não quero passar todas as variáveis como parâmetros, porque imho isso é um exagero.
Existe uma maneira diferente?
Respostas:
Você tem basicamente duas opções:
export TESTVARIABLE
) antes de executar o segundo script.. test2.sh
e ele será executado no mesmo shell. Isso permitiria compartilhar facilmente variáveis mais complexas, como matrizes, mas também significa que o outro script poderia modificar variáveis no shell de origem.ATUALIZAR:
Para usar
export
para definir uma variável de ambiente, você pode usar uma variável existente:Isso deve funcionar em ambos
bash
esh
.bash
também permite que ele seja combinado da seguinte maneira:Isso também funciona no meu
sh
(que por acaso ébash
, você pode usarecho $SHELL
para verificar). Mas eu não acredito que isso funcione de maneira garantidash
, então é melhor jogar com segurança e separá-los.Qualquer variável que você exportar dessa maneira será visível nos scripts executados, por exemplo:
cinza:
b.sh:
Então:
O fato de que esses dois scripts de shell também é incidental. As variáveis de ambiente podem ser passadas para qualquer processo que você executa, por exemplo, se usamos o python, pode parecer com:
cinza:
b.py:
Abastecimento:
Em vez disso, poderíamos fonte como esta:
cinza:
b.sh:
Então:
Isso "importa" mais ou menos
b.sh
diretamente o conteúdo e o executa no mesmo shell . Observe que não precisamos exportar a variável para acessá-la. Isso compartilha implicitamente todas as variáveis que você possui, além de permitir que o outro script adicione / exclua / modifique variáveis no shell. Obviamente, nesse modelo, os dois scripts devem ter o mesmo idioma (sh
oubash
). Para dar um exemplo de como podemos passar mensagens para frente e para trás:cinza:
b.sh:
Então:
Isso funciona igualmente bem
bash
. Também facilita o compartilhamento de dados mais complexos que você não pode expressar como uma variável de ambiente (pelo menos sem muita sobrecarga de sua parte), como matrizes ou matrizes associativas.fonte
Erro fatal deu uma possibilidade direta: forneça seu segundo script! se você está preocupado que esse segundo script possa alterar algumas de suas variáveis preciosas, você sempre pode fonte-lo em uma subshell:
Os parênteses farão com que a fonte aconteça em um subshell, para que o shell pai não veja que as modificações
test2.sh
poderiam ser executadas.Há outra possibilidade que definitivamente deve ser referenciada aqui: use
set -a
.Da referência POSIX
set
:No Manual do Bash :
Então, no seu caso:
Observe que as especificações especificam apenas que
set -a
a variável está marcada para exportação. Isso é:ecoará
c
e não uma linha vazia nemb
(isto é,set +a
não desmarca para exportação, nem "salva" o valor da atribuição apenas para o ambiente exportado). Este é, obviamente, o comportamento mais natural.Conclusão: usar
set -a
/set +a
pode ser menos tedioso do que exportar manualmente todas as variáveis. É superior ao fornecimento do segundo script, pois funcionará para qualquer comando, não apenas para os escritos na mesma linguagem shell.fonte
Na verdade, existe uma maneira mais fácil do que exportar e desconfigurar ou buscar novamente (pelo menos no bash, desde que você esteja bem em passar as variáveis de ambiente manualmente):
seja a.sh
e b.sh seja
A saída observada é
As mentiras mágicas na última linha
a.sh
, ondeMessage
, apenas para a duração da invocação./b.sh
, é definido para o valor desecret
partira.sh
. Basicamente, é um pouco como parâmetros / argumentos nomeados. Mais do que isso, porém, funciona até para variáveis como$DISPLAY
, que controla em qual X Server um aplicativo inicia.Lembre-se, o comprimento da lista de variáveis de ambiente não é infinito. No meu sistema com um kernel relativamente baunilha,
xargs --show-limits
diz-me que o tamanho máximo do buffer de argumentos é 2094486 bytes. Teoricamente, você está usando scripts de shell errados se seus dados forem maiores que isso (canais, alguém?)fonte
Adicionando à resposta de Erro fatal, há mais uma maneira de passar as variáveis para outro script de shell.
A solução sugerida acima tem algumas desvantagens:
using Export
: Fará com que a variável esteja presente fora do escopo, o que não é uma boa prática de design.using Source
: Pode causar colisões de nomes ou substituição acidental de uma variável predefinida em algum outro arquivo de script de shell que originou outro arquivo.Existe outra solução simples disponível para nós usarmos. Considerando o exemplo postado por você,
test.sh
test2.sh
resultado
Também é importante observar que
""
são necessários se passarmos seqüências de várias palavras. Tomando mais um exemplomaster.sh
slave1.sh
slave2.sh
resultado
Isso acontece devido aos motivos descritos adequadamente neste link
fonte
source
é realmente uma coisa boa. Em relação à sua preocupação: sobrescrever acidentalmente uma variável predefinida , você sempre pode procurar em uma subshell. Isso resolve completamente o problema.( . ./test2.sh )
. Os parênteses farão com que o Bash execute seu conteúdo em uma subshell.No Bash, se você exportar a variável dentro de um subshell, usando parênteses, como mostrado, evite vazar as variáveis exportadas:
A vantagem aqui é que, depois de executar o script na linha de comando, você não verá um $ TESTVARIABLE vazado em seu ambiente:
fonte
$
prompt da linha de comandos) nunca verá os exportados$TESTVARIABLE
. Exportar apenas passa uma cópia de uma variável para qualquer processo filho subsequente . Não é possível passar variáveis de backup da cadeia para processos pai, exceto salvando o valor no armazenamento e lendo esse armazenamento posteriormente no script do processo pai. É possível canalizar para uma segunda cópia do script pai, mas esse não seria o mesmo processo . Uma excelente explicação pode ser encontrada aqui .Outra opção está usando
eval
. Isso é adequado apenas se as strings forem confiáveis. O primeiro script pode ecoar as atribuições de variáveis:echo "VAR=myvalue"
Então:
eval $(./first.sh) ./second.sh
Essa abordagem é de particular interesse quando o segundo script para o qual você deseja definir variáveis de ambiente é não no bash e você também não deseja
export
as variáveis, talvez porque sejam sensíveis e você não queira que elas persistam.fonte
Outra maneira, que é um pouco mais fácil para mim, é usar pipes nomeados. Os pipes nomeados forneceram uma maneira de sincronizar e enviar mensagens entre diferentes processos.
A.bash:
B.bash:
Uso:
O B.bash aguardará a mensagem e, assim que o A.bash enviar a mensagem, o B.bash continuará seu trabalho.
fonte