POSIX Shell: 환경변수(Environment Variable)

환경변수는 시스템의 설정값이나 실행 경로 등, 운영체제 전반에 걸쳐 공유되어야 하는 정보를 담고 있습니다.

일반 변수 vs 환경 변수

가장 큰 차이점은 ‘전파(Inheritance)’입니다.

  • 일반 변수 (Local Variable): 현재 실행 중인 스크립트 내에서만 유효합니다.
  • 환경 변수 (Environment Variable): export 명령어를 통해 시스템의 ‘환경’으로 등록되어, 해당 쉘에서 실행하는 다른 스크립트나 프로그램에서도 읽을 수 있습니다.

export 명령어: 환경변수 만들기

일반 변수를 환경변수로 승격시킬 때 export를 사용합니다.

# 1. 선언과 동시에 export (가장 많이 쓰임)
export MY_APP_HOME="/usr/local/engcross"

# 2. 이미 있는 변수를 export
VERSION="2.1.0"
export VERSION

주요 표준 환경변수

POSIX 시스템(Linux, AIX 등)에서 미리 정의되어 자주 쓰이는 변수들입니다.

변수명설명
$PATH명령어를 찾을 디렉토리 경로 목록 (콜론 :으로 구분)
$HOME현재 사용자의 홈 디렉토리 경로
$USER현재 접속한 사용자 이름
$PWD현재 작업 디렉토리 (Print Working Directory)
$LANG시스템 언어 및 인코딩 (예: ko_KR.UTF-8)
$SHELL현재 사용 중인 쉘의 경로

실전 예제: PATH 변수 조작하기

내가 만든 스크립트를 어디서든 파일명만 입력해서 실행하고 싶을 때 $PATH를 수정합니다.

#!/bin/sh

# 현재 PATH 끝에 내 스크립트 폴더 추가
export PATH="$PATH:/home/lycos7560/bin"

# 이제 /home/lycos7560/bin 안에 있는 파일들은 
# 절대 경로 없이 이름만으로 실행 가능합니다.

환경변수 확인법

  • env: 현재 설정된 모든 환경변수 목록 출력
  • printenv PATH: 특정 환경변수(PATH)의 값만 출력
  • set: 환경변수뿐만 아니라 일반 변수, 함수까지 모두 포함해서 출력

주의사항: 변수의 수명

스크립트 내부에서 export한 변수는 그 스크립트가 종료되면 사라집니다.

  • 부모 쉘(터미널)에 적용하고 싶다면?

스크립트를 실행할 때 ./script.sh가 아닌 source ./script.sh 또는 . ./script.sh를 사용해야 합니다. (이를 Sourcing이라고 합니다.)

  • 영구히 적용하고 싶다면?

사용자의 홈 디렉토리에 있는 .profile (또는 .bash_profile) 파일에 export 구문을 적어두어야 로그인할 때마다 로드됩니다.

## parent.sh
#!/bin/sh
VAR1="Local"      # 일반 변수
export VAR2="Env" # 환경 변수

./child.sh        # 자식 프로세스 실행

## child.sh
#!/bin/sh
printf "VAR1: %s\n" "$VAR1" # 아무것도 안 나옴 (상속 안 됨)
printf "VAR2: %s\n" "$VAR2" # "Env" 출력 (상속 됨)

[결과]
$ ./parent.sh
VAR1: 
VAR2: Env

추가적으로 중요한 점은 자식이 가방(환경변수) 속 내용을 수정하거나 새 물건을 넣어도, 그 결과가 부모에게 돌아오지 않는다는 것입니다. 
자식이 종료되면 자식이 가졌던 가방 복사본은 그대로 파기되기 때문입니다.

환경에 따른 분기 (case문 결합)

#!/bin/sh

# 실행 환경(USER)에 따라 다른 설정 적용
case "$USER" in
    root)
        export LOG_LEVEL="DEBUG"
        export APP_PATH="/opt/app"
        ;;
    lycos7560)
        export LOG_LEVEL="INFO"
        export APP_PATH="/home/lycos7560/app"
        ;;
    *)
        printf "허용되지 않은 사용자입니다.\n"
        exit 1
        ;;
esac

printf "사용자: %s, 로그레벨: %s\n" "$USER" "$LOG_LEVEL"

환경변수는 스크립트가 외부 세계와 소통하는 통로입니다.

export를 통해 내가 만든 설정값을 하위 프로그램에 전달하고, $PATH$USER 같은 시스템 변수를 이용해 상황에 맞는 유연한 스크립트를 작성해 보세요!

자식에서 export로 변경하면 부모도 영향을 받나?

아니요. 부모는 전혀 영향을 받지 않습니다.

이것은 쉘 스크립트 시스템의 아주 중요한 철칙인 ‘일방통행 상속’ 때문입니다.

왜 부모는 영향을 받지 않나?

부모가 자식 프로세스를 만들 때, 부모의 환경변수를 그대로 주는 게 아니라 ‘복사본’을 복사해서 넘겨주기 때문입니다.

자식이 자기 손에 든 복사본 가방 안의 내용을 아무리 고치고 export를 다시 해도, 그것은 자신의 가방(자식 프로세스의 메모리) 내에서의 일일 뿐입니다.

부모의 가방(부모 프로세스의 메모리)은 멀리 떨어져서 보호받고 있습니다.

예시 코드로 확인하기

child.sh

#!/bin/sh
export MY_VAL="Changed by Child"
printf "자식: 값을 변경했습니다 -> %s\n" "$MY_VAL"

parent.sh

#!/bin/sh
export MY_VAL="Original Parent Value"

printf "부모: 실행 전 값 -> %s\n" "$MY_VAL"

# 자식 스크립트 실행
./child.sh

printf "부모: 자식 종료 후 값 -> %s\n" "$MY_VAL"

실행 결과:

부모: 실행 전 값 -> Original Parent Value
자식: 값을 변경했습니다 -> Changed by Child
부모: 자식 종료 후 값 -> Original Parent Value

자식이 부모의 환경을 바꾸고 싶을 땐?

자식 프로세스를 ‘별도로’ 띄우지 않고, 부모의 몸 안에서 직접 실행하게 하면 됩니다.

이것을 Sourcing(소싱)이라고 합니다.

  • 일반 실행 (./child.sh): 새로운 자식 쉘을 생성 (부모 영향 X)
  • 소싱 실행 (. ./child.sh): 현재 부모 쉘에서 코드를 그대로 읽어서 실행 (부모 영향 O)

이 개념은 보안과 안정성을 위한 개념입니다.

자식 프로그램이 멋대로 부모 시스템의 설정을 변경하면 문제가 되기 때문이죠.

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤