Use eval na sua linha final e verifique se o shell pai não come o $ :
#!/bin/bash
export FOO=bar
export BAR=baz
eval "$@"
funciona assim:
wouter@gangtai:~$ ./foo.sh echo '$BAR'
baz
Para mais informações, consulte help eval .
Meu serviço usa variáveis de ambiente extensivamente para configuração (principalmente porque é realmente fácil injetá-las em um contêiner Docker).
Eu também tenho alguns scripts de manutenção que posso executar em meu ambiente de produção. Mas como eu realmente não quero que o meu ambiente shell configurado para falar com o prod por padrão, eu tenho um script auxiliar que configura o ambiente e chama meu script de manutenção. O script auxiliar atualmente se parece com algo assim:
#!/bin/bash
export DB_NAME=foo
export DB_HOST=foo.service.local
export DB_USERNAME=testy_testerson
export DB_PASSWORD=password
export SERVICE_API_KEY=qwertyuiop
"$@"
E eu corro como bin/production_env.sh scripts/maintenance_script.sh arg1 arg2 . Isso tudo funciona muito bem.
Um dos meus scripts de manutenção é dump_db.sh , que é assim:
#!/bin/sh
pg_dump --no-owner --clean --if-exists --dbname "$DB_NAME" --host "$DB_HOST" --port "$DB_PORT" --username "$DB_USER" > "db/${RAILS_ENV}-dump.$(date +%Y-%m-%dT%H:%M:%S).sql"
Isso funciona muito bem também. Mas gostaria de poder executar comandos ad-hoc usando o ambiente configurado sem colocar essa lógica em um arquivo de script primeiro. por exemplo,
bin/production_env.sh psql --username "$DB_USER" --command 'select version()'
O problema, é claro, é que a variável DB_USER é expandida no meu shell atual, antes que a variável correta DB_USER esteja disponível.
Existe uma maneira conveniente de executar comandos ad-hoc como este, adiando a expansão de variáveis até a sub-camada? Ou está colocando meus comandos ad-hoc em um script da maneira mais fácil?
Você pode obter seu production_env.sh para testar sem argumentos (ou algum argumento único especial como -i ) e, em seguida, ler uma única linha (com -e para permitir a edição de entrada) e executá-lo. Por exemplo, mude sua última linha para:
if [ $# = 0 -a -t 0 ]
then read -p 'prod> ' -e cmd
bash -c "$cmd"
else "$@"
fi