bash - fonte sem poluir o próprio namespace [pegar variáveis de outros scripts de maneira segura]

3

Gostaria de atribuir o conteúdo de variáveis de outro script bash a variáveis no script de chamada.

Especificamente, eu source este arquivo: link (e outros arquivos semelhantes).

O arquivo contém variáveis chamadas depends , makedepends , etc.

Então no meu script eu tenho várias declarações como estas:

depends="$(source "/path/to/file" ; printf '%s' "${depends[@]}")"
makedepends="$(source "/path/to/file" ; printf '%s' "${makedepends[@]}")"
...

Então, basicamente, cada instrução inicia seu próprio subshell que origina o arquivo e imprime o conteúdo de apenas UMA variável em uma variável no shell pai.

Existe outra maneira que envolve iniciar apenas uma sub-pasta SINGLE , fonte do arquivo e obter o conteúdo das variáveis especificadas do arquivo atribuído às variáveis especificadas no shell de chamada sem poluir o ambiente do shell de chamada?

----------------------------------------------- -------------------------

Desde que Mark Mann apontou os perigos de source -ing scripts estrangeiros, acabei com outra solução. Em vez de usar source para obter variáveis de outro script, pode-se usar uma linha múltipla grep com um perl regex para grep todas as variáveis necessárias do arquivo (varName = (...), varName2=".. . ", varname3 = '...', varName4 = ...) e eval o resultado:

$ grepvars='(license)|(depends)|(makedepends)|(url)|(pkgdesc)|(pkgver)'
$
$ eval $(grep -Pzo "^(${grepvars})=\([^\)\(\']*\)|^(${grepvars})=\"[^\"\(\']*\"|^(${grepvars})='\''[^'\'']*'\''|^(${grepvars})=[^\s;\(\']*" /tmp/above_mentioned_file)
$ echo $url
https://www.mozilla.org/firefox/
$
$ echo ${depends[@]}
gtk3 gtk2 mozilla-common libxt startup-notification mime-types dbus-glib alsa-lib ffmpeg2.8 desktop-file-utils hicolor-icon-theme libvpx icu libevent nss hunspell sqlite ttf-font
    
por MCH 29.02.2016 / 23:52

3 respostas

6

Use eval .

Se você tiver sua fonte (em /tmp/other.sh):

a=1
b=2
c=3

E você quer apenas uma parte, você pode usar eval para obter apenas esses itens (aqui em /tmp/main.sh):

eval $(source /tmp/other.sh;
       echo a="$a";
       echo b="$b";)

echo a is $a "(expect 1)"
echo b is $b "(expect 2)"
echo c is $c "(expect nothing)"

e executá-lo:

$ bash /tmp/main.sh
a is 1 (expect 1)
b is 2 (expect 2)
c is (expect nothing)

AVISO : executar um eval ou source em um script não confiável é muito perigoso. Você está executando um script de shell e esse script pode executar qualquer coisa que você possa fazer sozinho. AVISO

    
por 01.03.2016 / 00:09
3

Sem usar eval , você ainda pode fazer isso por meio da substituição de processo, se estiver usando bash ou similar:

source <(source "/path/to/file" ; printf %s\n "depends=${depends[*]}" "makedepends=${makedepends[*]}")

Isso inicia uma subshell e origina o arquivo, assim como seu exemplo inicial, mas em vez de imprimir diretamente o valor e usar a substituição de comando, ele imprime o valor formatado como uma atribuição e origina a saída usando a substituição de processo. >

Isso responde exatamente à seguinte parte da sua pergunta:

Is there another way which involves to start just a SINGLE subshell, source the file and get the contents of specified variables of the file assigned to specified variables in the calling shell without polluting the environment of the calling shell?

Mas é claro que os perigos de se terceirizar scripts estrangeiros ainda se aplicam. Não crie um script não confiável, nunca.

Se você mesmo escreveu o roteiro e está absolutamente certo que ele não tem efeitos colaterais (e não produz saída), você pode usar o acima para seu próprio computador pessoal . Não é algo que sempre esteja em um script de produção. Buraco de segurança muito grande.

    
por 01.03.2016 / 20:59
1

source <(cat "/path/to/file" | grep "depends\|makedepends")

O /path/to/file não é originado de forma alguma (vs. a abordagem do Wildcard). Veja a discussão sobre insegurança acima. Além disso, se for, por exemplo, .env file de docker-compose ou similar, ele poderia ser usado de forma a desenhar variáveis por outros scripts sem executar variáveis sem aspas, aquelas que podem causar erros de execução. Por exemplo - traefik regra de frontend como, WEB_FRONTEND_RULE=Host:my.host.name;PathPrefix:/my-path-prefix , que é válida em docker-compose .env , não é válida para ser obtida por bash . E WEB_FRONTEND_RULE='Host:my.host.name;PathPrefix:/my-path-prefix' é válido para ser originado por bash , mas não é válido em docker-compose .env .

    
por 24.10.2018 / 10:21