Use printenv
em vez , que não requer um shell:
capture('printenv ENV_VAR')
Substitua ENV_VAR
pelo nome da variável de ambiente desejada. Não prefixar $
.
Embora printenv
seja não POSIX , GNU / Linux sistemas como Debian, Ubuntu, Fedora e CentOS suportam porque GNU Coreutils fornece, e funciona em muitos outros sistemas * nix , como o FreeBSD. O motivo pelo qual você precisa usar printenv
em vez de env
é que printenv ENV_VAR
gera o valor de ENV_VAR
, enquanto env ENV_VAR
tenta executar um comando chamado ENV_VAR
, que não é o que você quer.
O restante deste post abrange outros métodos, suas limitações e como eles podem ser melhorados. Esta é uma leitura opcional, já que printenv
é simples e resolve completamente o problema.
Seu método original , capture("env | grep ENV_VAR").split("=").last
, não deve ser usado nem mesmo em um sistema em que parece funcionar, porque não é confiável. É grep
s para o nome da variável em todos os lugares na linha VAR=val
, e assim retornará resultados para variáveis cujos nomes - ou mesmo valores - contenham o nome da variável desejada. Usar ^ENV_VAR=
em vez de ENV_VAR
corrige esse problema, combinando o nome apenas quando ele aparecer na início da linha ( ^
) e exigir que um caractere =
apareça logo após. No entanto, é possível que o valor de uma variável de ambiente contenha um caractere =
e, como você chama split
e last
, na verdade, você obtém a substring posterior mais longa do valor que não contém =
. Mesmo se você consertou isso, o método ainda é desnecessariamente complexo quando tudo que você precisa é printenv
.
A solução que você encontrou , capture("/bin/sh -c 'echo $ENV_VAR'")
, funcionará mais de o tempo , mas retornará um valor incorreto quando a variável (a) contiver espaço em branco diferente de caracteres de espaço simples cercados por espaços não brancos, ou (b) contém caracteres globbing como *
, ?
e [
se eles corresponderem a qualquer nome de arquivo. O problema é que, no comando shell echo $ENV_VAR
, a expansão do parâmetro $ENV_VAR
não é citado , então divisão de palavras e globbing são executados. echo
reinsere o espaço em branco, mas nem sempre da mesma maneira: echo foo bar
imprime foo bar
, mas echo foo bar
. Esse problema pode ser resolvido colocando-se "
"
citações ao redor da expansão, embora você tenha que escapar delas para que o interpretador Ruby não as conclua como finalizando o "
-quoted string e iniciando um novo, ou você pode '
-quote a string Ruby e escape de qualquer caractere '
interno.
Você também obtém um resultado errado na situação menos comum em que o valor ENV_VAR
começa com uma opção que echo
suporta. Diferentes implementações de echo
suportam diferentes opções; -n
e -e
são comuns. A maioria dos shells tem echo
como um builtin e pode suportar diferentes opções de outros shells e de /bin/echo
. Isso é para dizer que echo
não é muito portátil . É razoável inspecionar as variáveis de ambiente de forma interativa, quando você provavelmente perceberá se algo estranho está acontecendo, mas menos para o script. Os problemas de portabilidade de echo
são exacerbados pela forma como /bin/sh
nem sempre é bash
. No Ubuntu ele é dash
. Isso pode ser evitado usando printf '%s\n'
ou printf "%s\n"
em vez de echo
(ou , no seu caso, printf %s
pode ser suficiente).
Assim, sua solução pode ser melhorada para capture('/bin/sh -c \'printf "%s\n" "$ENV_VAR"\'')
. Isso pode parecer errado para os shell scripters experientes que não conhecem Ruby; Observe que, ao contrário do Bash e de outros shells no estilo Bourne, Ruby trata \'
como uma literal '
dentro de uma string '
'
-quoted. Mesmo que esteja correto, seus colegas terão que examiná-lo duas vezes para se certificarem disso, mesmo que sejam proficientes em scripts de shell e Ruby. capture('printenv ENV_VAR')
é mais simples.