변수 확장을 서브쉘로 연기

변수 확장을 서브쉘로 연기

내 서비스는 구성을 위해 환경 변수를 광범위하게 사용합니다(주로 Docker 컨테이너에 삽입하기가 매우 쉽기 때문입니다).

또한 프로덕션 환경에서 실행할 수 있는 유지 관리 스크립트도 있습니다. 하지만 나 이후로진짜기본적으로 제품과 통신하도록 쉘 환경을 구성하기보다는 환경을 설정한 다음 유지 관리 스크립트를 호출하는 도우미 스크립트를 사용합니다. 도우미 스크립트는 현재 다음과 같습니다.

#!/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
"$@"

나는 그것을 bin/production_env.sh scripts/maintenance_script.sh arg1 arg2. 이것은 모두 좋습니다.

내 유지 관리 스크립트 중 하나는 dump_db.sh아래와 같습니다.

#!/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"

이것도 훌륭하게 작동합니다. 하지만 먼저 해당 논리를 스크립트 파일에 넣을 필요 없이 구성된 환경을 사용하여 임시 명령을 실행할 수 있기를 원합니다. 예를 들어,

bin/production_env.sh psql --username "$DB_USER" --command 'select version()'

물론 문제는 DB_USER올바른 변수를 사용할 수 DB_USER있기 전에 현재 셸에서 변수가 확장된다는 것입니다.

서브셸에 대한 변수 확장을 연기하여 이와 같은 임시 명령을 실행하는 편리한 방법이 있습니까? 아니면 임시 명령을 스크립트에 넣는 것이 가장 쉬운 방법입니까?

답변1

마지막 줄에 이것을 사용 eval하고 상위 쉘이 그것을 먹지 않는지 확인하십시오 $.

#!/bin/bash
export FOO=bar
export BAR=baz
eval "$@"

다음과 같이 실행하세요:

wouter@gangtai:~$ ./foo.sh echo '$BAR'
baz

자세한 내용은 을 참조하십시오 help eval.

답변2

테스트에서 production_env.sh인수를 사용하지 않고(또는 특수 단일 인수(예: -i)) 한 다음 한 줄을 읽고( -e편집용 입력 허용) 실행할 수 있습니다. 예를 들어 마지막 줄을 다음과 같이 변경합니다.

if [ $# = 0 -a -t 0 ]
then read -p 'prod> ' -e cmd
     bash -c "$cmd"
else "$@"
fi

관련 정보