Bash 5.x · Linux 사용자 공간

Bash 변수는 어디까지 유지될까요?

if문, 함수, 서브셸을 구분하고 변수 값이 자식 프로세스에 전달되는 과정을 확인합니다.

if문이 끝나도 변수는 남습니다

Bash의 if는 조건에 따라 명령을 실행합니다. 그 자체로 새 변수 범위나 새 프로세스를 만들지는 않습니다. 조건문 안에서 값을 바꾸면 같은 셸의 변수가 바뀝니다.

value=before
if true; then
    value=after
fi
printf '%s\n' "$value"

출력은 after입니다. true가 성공하므로 대입문을 실행하고, fi를 지난 뒤에도 그 값을 읽습니다. 반대로 조건이 거짓이면 대입문을 실행하지 않아 기존 값이 유지됩니다.

같은 셸에서 실행한 조건문의 상태 변화
  1. 조건문 직전value = before
  2. 조건이 참이면 대입같은 변수의 값을 after로 바꿉니다.
  3. 조건문 다음 명령value = after를 읽습니다.

위에서 아래로 실행 순서를 나타냅니다. 세 상자 모두 같은 셸의 상태입니다.

값이 분리되는 경계를 확인합니다

형태변경이 남는 곳
if …; then …; fi, { …; }같은 셸입니다. 묶었다는 이유만으로 변수 범위가 생기지 않습니다.
함수의 일반 대입기본적으로 호출한 셸의 변수를 바꿉니다. 함수 안에서 local을 사용하면 지역 변수를 만들 수 있습니다.
( … )서브셸 환경에서 바뀝니다. 바깥 셸의 값은 유지됩니다.
bash child.sh새 Bash에서 바뀝니다. 종료할 때 부모 변수에 자동으로 반영되지 않습니다.
source ./child.sh현재 Bash에서 파일을 읽어 실행합니다. 변수와 작업 디렉터리 변경도 현재 셸에 남습니다.
value=parent
( value=child; printf 'inside=%s\n' "$value" )
printf 'outside=%s\n' "$value"

출력은 inside=child, outside=parent입니다. 괄호 안의 대입이 부모의 변수 저장 공간을 고치는 것은 아닙니다. 함수의 local은 C의 중괄호 범위와도 다릅니다. Bash는 동적 범위를 사용하므로 호출된 함수가 호출자의 지역 변수를 볼 수 있습니다.

export는 이후 실행할 프로그램에 값을 전달합니다

NOTE_VALUE=parent
export NOTE_VALUE
bash -c 'printf "child=%s\n" "$NOTE_VALUE"; NOTE_VALUE=changed'
printf 'parent=%s\n' "$NOTE_VALUE"
명령무엇이 바뀌나요?
NOTE_VALUE=parent현재 셸에 문자열 값을 저장합니다.
export NOTE_VALUE이 변수를 이후 실행하는 명령의 환경에 포함하도록 표시합니다.
bash -c …자식은 전달받은 parent를 출력한 뒤 자신의 값을 changed로 바꿉니다.
마지막 printf부모는 여전히 parent를 출력합니다.

이미 실행 중인 다른 프로세스에 값이 퍼지는 것은 아닙니다. 셸이 종료되면 그 셸의 변수는 없어지지만, 먼저 실행되어 값을 상속받은 자식의 환경까지 지워지지는 않습니다.

env -i command는 그 명령에 빈 환경을 전달하며 부모 셸의 변수를 삭제하지 않습니다. 설정 파일에서 export 줄을 지운 뒤 source해도 이미 저장된 값은 자동으로 없어지지 않습니다. 현재 셸에서 제거하려면 해당 변수의 unset 여부를 따로 정해야 합니다. set과 env 역시 각각 셸 상태와 명령의 환경을 보여 주는 것이며 시스템의 모든 프로세스 변수를 한꺼번에 조회하는 명령은 아닙니다.

${value}와 $(command)는 다른 문법입니다

value='hello world'
printf '%s\n' "${value}"
result=$(printf '%s\n' 'hello world')
printf '%s\n' "$result"

${value}는 변수 값을 꺼내고, $(…)는 안의 명령을 실행한 표준 출력을 가져옵니다. 따라서 $(value)는 value라는 명령을 실행하려는 표현입니다. 명령 치환은 끝부분의 개행을 제거합니다.

값을 다른 명령의 인자로 넘길 때 "$value"처럼 큰따옴표로 감싸면 공백 분리와 파일 이름 확장을 막을 수 있습니다. 대입문의 = 양옆에는 공백을 넣지 않습니다.

확인한 문서

Bash 5.x · Linux 사용자 공간