iBetter Books
수정

환경변수와 특수변수

Bash를 열면 이미 수십 개의 변수가 설정되어 있습니다. 여러분이 선언하지 않았는데도 $HOME에 홈 디렉토리가 들어있고, $PATH에는 명령어 검색 경로가 있습니다. 이것이 환경변수입니다. 그리고 Bash가 자동으로 관리하는 특수변수도 있습니다. 이것들을 제대로 알면 스크립트가 훨씬 유연해집니다.

주요 환경변수

$ env | head -20

env 명령어를 실행하면 현재 설정된 환경변수 전체를 볼 수 있습니다. 자주 쓰는 것들을 정리하면 다음과 같습니다.

변수 설명 예시 값
PATH 명령어 검색 디렉토리 목록 /usr/local/bin:/usr/bin:/bin
HOME 현재 사용자의 홈 디렉토리 /home/user
USER 현재 로그인한 사용자명 ibetter
SHELL 현재 사용 중인 쉘 경로 /bin/bash
LANG 시스템 언어 설정 ko_KR.UTF-8
PWD 현재 작업 디렉토리 /home/user/scripts
OLDPWD 이전 작업 디렉토리 /home/user
#!/bin/bash# 새 파일: scripts/env_info.shecho "사용자: ${USER}"echo "홈 디렉토리: ${HOME}"echo "쉘: ${SHELL}"echo "현재 디렉토리: ${PWD}"echo "이전 디렉토리: ${OLDPWD:-없음}"echo ""echo "PATH 항목들:"# PATH를 콜론으로 분리해서 각 줄에 출력echo "${PATH//:/$'\n'}"exit 0

실행 결과는 다음과 같습니다.

$ bash scripts/env_info.sh
사용자: ibetter
홈 디렉토리: /home/ibetter
쉘: /bin/bash
현재 디렉토리: /home/ibetter/scripts
이전 디렉토리: 없음

PATH 항목들:
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin

export — 환경변수 전달

일반 변수는 현재 쉘에서만 사용할 수 있습니다. export로 내보내면 자식 프로세스(서브쉘, 실행된 명령어 등)도 접근할 수 있습니다.

# 일반 변수는 서브쉘에서 보이지 않음local_var="나는 지역 변수"bash -c 'echo "서브쉘: ${local_var}"'    # 출력 없음# export하면 서브쉘에서도 보임export exported_var="나는 환경변수"bash -c 'echo "서브쉘: ${exported_var}"'  # 출력: 서브쉘: 나는 환경변수

스크립트 안에서 선언하고 바로 export할 수도 있습니다.

export APP_ENV="production"export DB_HOST="localhost"

특수변수

Bash가 자동으로 설정하는 변수들입니다. 이름을 직접 바꿀 수 없습니다.

#!/bin/bash# 새 파일: scripts/special_vars.sh# 이 스크립트를 실행할 때 인자를 넘겨주세요# 예: bash scripts/special_vars.sh 홍길동 25 서울echo "스크립트 이름: $0"echo "첫 번째 인자: $1"echo "두 번째 인자: $2"echo "세 번째 인자: $3"echo "인자 개수: $#"echo "현재 PID: $$"echo ""echo "모든 인자 (\$@):"for arg in "$@"; do  echo "  - ${arg}"doneecho ""echo "모든 인자 (\$*):"for arg in "$*"; do  echo "  - ${arg}"doneexit 0

실행 결과는 다음과 같습니다.

$ bash scripts/special_vars.sh 홍길동 25 서울
스크립트 이름: scripts/special_vars.sh
첫 번째 인자: 홍길동
두 번째 인자: 25
세 번째 인자: 서울
인자 개수: 3
현재 PID: 12345

모든 인자 ($@):
  - 홍길동
  - 25
  - 서울

모든 인자 ($*):
  - 홍길동 25 서울

특수변수를 정리하면 다음과 같습니다.

변수 의미
$0 스크립트 이름(경로 포함)
$1 ~ $9 위치 매개변수 (첫 번째 ~ 아홉 번째 인자)
${10} 이상 열 번째 이후 인자는 중괄호 필요
$# 전달된 인자 개수
$@ 모든 인자를 각각 별도 항목으로
$* 모든 인자를 하나의 문자열로
$? 직전 명령어의 종료 코드
$$ 현재 스크립트의 PID
$! 마지막으로 백그라운드 실행한 프로세스의 PID

$@ vs $*의 차이

인자에 공백이 포함된 경우에 차이가 드러납니다.

#!/bin/bash# 새 파일: scripts/at_vs_star.shecho "--- \$@ 사용 ---"for arg in "$@"; do  echo "  항목: [${arg}]"doneecho ""echo "--- \$* 사용 ---"for arg in "$*"; do  echo "  항목: [${arg}]"doneexit 0
$ bash scripts/at_vs_star.sh "첫 번째" "두 번째" "세 번째"
--- $@ 사용 ---
  항목: [첫 번째]
  항목: [두 번째]
  항목: [세 번째]

--- $* 사용 ---
  항목: [첫 번째 두 번째 세 번째]

"$@"는 각 인자를 독립된 항목으로 보존합니다. "$*"는 모든 인자를 공백으로 이어 붙여 하나의 문자열로 만듭니다. 반복문에서 인자를 처리할 때는 거의 항상 "$@"를 씁니다.

env, printenv, set 비교

환경변수를 확인하는 명령어가 여러 개라 헷갈릴 수 있습니다.

명령어 보여주는 것 특징
env 환경변수 실행 환경에서 명령어도 실행 가능
printenv 환경변수 특정 변수 하나만 볼 때 편리
set 환경변수 + 쉘 변수 + 함수 현재 쉘의 모든 것을 보여줌
# 특정 변수 하나 확인printenv HOME# 변수가 환경변수인지 확인env | grep MY_VAR

set은 출력이 매우 많아서 grep과 함께 쓰는 것이 좋습니다.