infra
Platform

모듈 맵

[Linux] 서버 설정의 기초인 export, .bashrc, .profile 완벽 정리

0 / 37 완료

펼치기
0 / 37 완료0%

리눅스 서버 운영 · 09 / 37

[Linux] 서버 설정의 기초인 export, .bashrc, .profile 완벽 정리

$PATH, .bashrc, .bash_profile을 완전히 이해하고 개발 환경을 자유롭게 설정합니다

🚨INCIDENT ALERT
HIGH

새 서버에 접속했더니 python3 명령어는 실행되는데 pythoncommand not found가 납니다. .bashrc에 PATH를 추가했는데 재접속해도 반영이 안 됩니다. cron에 등록한 스크립트는 터미널에서 잘 되는데 자동 실행하면 항상 실패합니다.

이 모든 상황의 공통 원인은 환경변수와 dotfiles를 모르기 때문입니다. 이 모듈을 마치면 PATH 추적, 설정 즉시 적용, cron 환경변수 문제를 스스로 진단하고 해결할 수 있게 됩니다.

환경변수 & dotfiles

이번 챕터에서 배울 것
  • 1지역 변수와 export 환경변수의 차이를 이해하고 자식 프로세스 전달 범위를 설명할 수 있다
  • 2env, printenv, set으로 환경변수를 조회하고 unset으로 제거할 수 있다
  • 3.bashrc와 .bash_profile의 로드 순서와 적용 시점 차이를 설명할 수 있다
  • 4$PATH 구조를 이해하고 새 경로를 추가해 언어 런타임 버전을 전환할 수 있다
  • 5source로 설정을 즉시 적용하고, alias를 영구 등록하며, cron 스크립트에서 누락된 환경변수를 보완할 수 있다
실습 환경 준비
현재 환경변수 전체 목록 확인
env | sort
PATH 현재 값 확인
echo $PATH | tr ':' '\n'
.bashrc 편집 후 즉시 적용
source ~/.bashrc
/etc/environment 수정 시 주의

셸 스크립트 문법(export, 변수 치환)을 지원하지 않으므로 KEY=VALUE 형식만 사용합니다

💡개념

지역 변수 vs 전역 환경변수 — export의 역할

배포 스크립트를 짜다 보면 스크립트 안에서 설정한 변수가 자식 스크립트에서 안 보이는 상황을 만납니다. 또는 반대로, 터미널에서 export DB_HOST=localhost를 설정했는데 cron으로 실행하면 해당 변수가 없다는 에러가 납니다. 이 차이가 지역 변수와 환경변수의 구분에서 비롯됩니다. export를 붙이느냐 마느냐 한 단어 차이지만, 그 변수가 자식 프로세스에 전달되는지가 달라집니다. 스크립트 간 데이터 전달, 환경 설정 파일 구조 설계, cron 오류 디버깅 — 이 모든 상황에서 이 개념이 기준점이 됩니다.

쉘에서 변수를 만드는 방법은 두 가지입니다. export 여부에 따라 그 변수가 자식 프로세스에게 전달되는지가 결정됩니다.

환경변수 — export와 자식 프로세스 상속, dotfiles 로드 순서확대

지역 변수 (Local Variable)

현재 쉘 세션에만 존재하며, 자식 프로세스(새 쉘, 실행한 스크립트 등)에는 전달되지 않습니다.

로컬 터미널
# 지역 변수 선언
MY_NAME="alice"
echo $MY_NAME
# 출력: alice

# 자식 쉘에서는 보이지 않음
bash -c 'echo $MY_NAME'
# 출력: (아무것도 출력 안 됨)

전역 환경변수 (Environment Variable) — export 사용

export를 사용하면 현재 쉘과 그 쉘에서 실행되는 모든 자식 프로세스에게 변수가 전달됩니다.

로컬 터미널
# 환경변수로 내보내기
export MY_NAME="alice"

# 자식 쉘에서도 접근 가능
bash -c 'echo $MY_NAME'
# 출력: alice

# 선언과 동시에 export
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk"

# 기존 지역 변수를 나중에 export
VERSION="3.11"
export VERSION

변수 확인 방법 비교env, printenv, set 명령어가 각각 어떤 변수를 보여주는지 비교합니다:

명령어보여주는 것
set지역 변수 + 환경변수 + 쉘 함수 모두
env현재 프로세스의 환경변수만
printenv환경변수만 (특정 변수 지정 가능)
printenv HOMEHOME 변수 하나만 출력
로컬 터미널
# 환경변수 전체 목록
env
# 출력 예시:
# HOME=/home/alice
# USER=alice
# SHELL=/bin/bash
# LANG=en_US.UTF-8
# PATH=/usr/local/bin:/usr/bin:/bin
# TERM=xterm-256color
# ...

# 특정 변수만 확인
printenv HOME
# 출력: /home/alice

printenv JAVA_HOME
# 출력: /usr/lib/jvm/java-17-openjdk

# set은 함수와 지역 변수까지 포함하므로 출력이 매우 많음
# 특정 변수를 찾을 때는 grep과 함께 사용
set | grep MY_NAME
# 출력: MY_NAME=alice

변수 삭제unset 명령으로 환경변수나 쉘 변수를 제거합니다:

로컬 터미널
unset MY_NAME
echo $MY_NAME
# 출력: (빈 줄)

중요한 개념: export는 현재 세션과 그 자식들에게만 적용됩니다. 다음 로그인 세션에서도 환경변수를 유지하려면 반드시 dotfile(.bashrc 또는 .bash_profile)에 기록해야 합니다.


환경변수 선언과 제거(export와 unset)

환경변수 안전하게 지우기: unset

unset현재 셸의 변수 이름과 값을 제거해 이후에 시작하는 자식 프로세스로 더 이상 상속되지 않게 합니다. 이미 실행 중인 프로세스가 가진 환경 사본, 셸 히스토리, CI 로그·프로세스 목록 등에 남은 값까지 지우는 명령은 아니므로 비밀값을 안전하게 폐기하는 만능 방법으로 오해하면 안 됩니다.

⚠️ 비밀번호·토큰은 명령줄 인자나 echo로 출력하지 말고 Secret Manager/CI 보안 변수로 주입하세요. 사용 후에는 unset하고, 노출 가능성이 있으면 해당 자격증명을 즉시 폐기·교체하고 로그를 정리합니다.

로컬 터미널
$ export MY_VAR="secret"
$ unset MY_VAR
$ echo $MY_VAR # 아무것도 출력되지 않음

PATH 환경변수 확장 시의 덮어쓰기 참사 예방

새 소프트웨어 바이너리 경로를 $PATH에 추가할 때, 기존 경로를 누락하는 중대한 실수를 저지르면 ls, cp 같은 시스템 기본 명령어가 먹통이 됩니다. 반드시 기존 $PATH를 뒤에 붙여 확장해야 합니다.

로컬 터미널
# 올바른 예시 (기존 PATH를 포함하여 뒤에 붙임)
$ export PATH="/opt/newapp/bin:$PATH"

# 절망적인 오답 예시 (기존 PATH 유실, 기본 명령어 마비됨!)
$ export PATH="/opt/newapp/bin"
💡개념

dotfiles 로드 순서 — 언제 어떤 파일이 실행되는가

dotfiles 로드 순서 — Login Shell vs Interactive Shell, 파일별 적용 범위확대

Linux 쉘은 시작 조건에 따라 서로 다른 설정 파일을 읽습니다. 이 순서를 모르면 "분명히 .bashrc에 썼는데 왜 적용이 안 되지?"라는 상황에 빠집니다.

쉘의 두 가지 시작 모드 — Login Shell과 Non-Login Shell은 로드하는 설정 파일이 다릅니다:

모드설명예시
Login Shell로그인 시 최초로 실행되는 쉘SSH 접속, 콘솔 로그인, bash --login
Interactive Non-Login Shell이미 로그인된 상태에서 새 터미널 열기터미널 에뮬레이터, bash 명령 실행
Non-Interactive Shell사용자 입력 없이 실행되는 쉘스크립트 실행, cron 작업

로드 순서 — Login Shell (SSH 접속 등) — SSH 접속 시 쉘이 읽는 파일 순서입니다:

1. /etc/profile          ← 시스템 전체 설정 (root만 수정)
2. /etc/profile.d/*.sh   ← 패키지가 추가하는 개별 설정 파일들
3. ~/.bash_profile       ← 사용자 로그인 설정 (없으면 아래 순서로 시도)
   또는 ~/.bash_login
   또는 ~/.profile

로드 순서 — Interactive Non-Login Shell (새 터미널 탭) — 터미널 앱에서 새 탭을 열 때 읽는 파일 순서입니다:

1. /etc/bash.bashrc      ← 시스템 전체 interactive 설정
2. ~/.bashrc             ← 사용자 interactive 설정

실무에서 쓰는 표준 패턴:

대부분의 Linux 배포판에서 ~/.bash_profile~/.bashrc를 직접 불러오도록 설정되어 있습니다. 이렇게 하면 로그인 쉘이든 인터랙티브 쉘이든 동일한 설정이 적용됩니다.

로컬 터미널
# ~/.bash_profile 일반적인 내용
# Login shell에서 .bashrc를 읽도록 연결
if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi

이 패턴 덕분에 개발자가 실제로 수정하는 파일은 거의 항상 ~/.bashrc 하나입니다.

시스템 전역 vs 사용자별 설정 — 어느 파일을 수정하느냐에 따라 적용 범위와 필요 권한이 달라집니다:

파일적용 범위수정 권한
/etc/environment시스템 전체 (모든 사용자, 모든 쉘)root
/etc/profile시스템 전체 login shellroot
/etc/profile.d/*.sh시스템 전체 (패키지별 분리)root
~/.bash_profile해당 사용자 login shell해당 사용자
~/.bashrc해당 사용자 interactive shell해당 사용자

/etc/environment 특이점 — 이 파일은 쉘 문법이 아닌 단순 KEY=VALUE 형식만 허용합니다:

로컬 터미널
# /etc/environment는 쉘 스크립트가 아닙니다
# export 키워드 없이 KEY=VALUE 형식만 사용
cat /etc/environment
# 출력:
# PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# LANG="en_US.UTF-8"

# 이 파일은 PAM(Pluggable Authentication Modules)이 읽으므로
# SSH, GUI 로그인, sudo 등 모든 경우에 적용됨

어떤 파일에 무엇을 써야 하는가:

  • ~/.bashrc: alias, 함수, PATH 추가, 프롬프트(PS1) 설정 — 대부분의 개인 설정
  • ~/.bash_profile: 로그인 시 한 번만 실행되어야 하는 것 (보통 .bashrc 호출만)
  • /etc/environment: 시스템 전체에 적용할 단순 KEY=VALUE 변수 (쉘 문법 사용 불가)

환경변수·PATH 판단 — 어디에 무엇을 써야 적용되나
alias·함수를 영구 적용하고 싶다.bashrc에. 대화형 셸이 열릴 때마다 읽힘. .profile에 넣으면 SSH 대화형 로그인 외엔 안 먹는 경우가 생긴다
PATH 같은 전역 환경변수를 영구 적용.profile 또는 .bash_profile에 export. 로그인 셸 1회 평가 → 자식 프로세스로 상속. 'export 안 하면 자식에게 안 넘어간다'
GUI 앱·systemd 서비스에도 변수가 필요.bashrc/.profile은 셸 전용 — GUI·systemd엔 안 닿음. systemd는 Environment=/EnvironmentFile=, 전역은 /etc/environment에
PATH에 내 디렉토리를 앞 vs 뒤내 바이너리로 시스템 것을 덮어쓰려면 앞($HOME/bin:$PATH), 보조용이면 뒤. 앞에 두면 같은 이름일 때 내 것이 우선 — 의도치 않은 가로채기 주의
command not found가 떴다echo $PATH로 경로 누락 확인, which/type으로 위치 확인. 설치는 됐는데 안 잡히면 거의 PATH 문제 — 설치 위치가 PATH에 없는 것
수정했는데 적용 안 됨source ~/.bashrc로 현재 셸에 즉시 반영(재로그인 불필요). 새 변수가 자식에게 안 보이면 export 누락 여부부터 — '선언≠전파'

실습 — 기본기 다지기

실습 전 디렉토리와 예제 파일을 먼저 준비합니다.

로컬 터미널
# 실습 디렉토리 준비
mkdir -p /tmp/linux/part2/exam_11 && cd /tmp/linux/part2/exam_11

# .env 파일 생성
cat > /tmp/linux/part2/exam_11/.env << 'EOF'
APP_ENV=development
DB_HOST=localhost
DB_PORT=5432
APP_PORT=8080
SECRET_KEY=dev-secret-change-in-prod
EOF

# 환경변수 로드 테스트 스크립트 생성
cat > /tmp/linux/part2/exam_11/app.sh << 'EOF'
#!/bin/bash
source .env
echo "Environment: $APP_ENV"
echo "DB: $DB_HOST:$DB_PORT"
echo "App Port: $APP_PORT"
EOF
chmod +x /tmp/linux/part2/exam_11/app.sh

이제 실습을 진행합니다.

현재 환경변수 전체 탐색하기

서버에 처음 접속했을 때 현재 환경이 어떻게 설정되어 있는지 파악하는 것이 첫 번째 습관입니다.

로컬 터미널
# 모든 환경변수 출력 (알파벳 정렬)
env | sort

출력 예시:

DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
HOME=/home/alice
LANG=en_US.UTF-8
LOGNAME=alice
MAIL=/var/mail/alice
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/alice/.local/bin:/home/alice/bin
PWD=/home/alice
SHELL=/bin/bash
TERM=xterm-256color
USER=alice
XDG_RUNTIME_DIR=/run/user/1000
로컬 터미널
# 특정 변수 하나만 확인
printenv PATH
# 출력: /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/alice/.local/bin

# 변수 존재 여부 확인 (스크립트에서 유용)
if [ -z "$JAVA_HOME" ]; then
    echo "JAVA_HOME이 설정되지 않았습니다"
fi
# 출력: JAVA_HOME이 설정되지 않았습니다

# 현재 로그인한 사용자 확인
echo "사용자: $USER, 홈 디렉토리: $HOME, 쉘: $SHELL"
# 출력: 사용자: alice, 홈 디렉토리: /home/alice, 쉘: /bin/bash

자주 사용하는 내장 환경변수 — 쉘이 기본으로 제공하는 변수들로 경로, 사용자, 홈 디렉터리 등을 담고 있습니다:

로컬 터미널
echo $HOME      # 홈 디렉토리: /home/alice
echo $USER      # 현재 사용자: alice
echo $SHELL     # 기본 쉘: /bin/bash
echo $PWD       # 현재 디렉토리: /home/alice/projects
echo $OLDPWD    # 이전 디렉토리 (cd - 명령의 동작 원리)
echo $HOSTNAME  # 호스트명: web-server-01
echo $LANG      # 언어 설정: en_US.UTF-8
echo $TERM      # 터미널 타입: xterm-256color
echo $$         # 현재 쉘의 PID: 12345
echo $?         # 직전 명령의 종료 코드: 0 (성공) 또는 1 이상 (실패)
🔍실행 후 확인할 것
  • 먼저 env | sort 출력에서 PATH 항목을 찾는다 — 그 다음 echo $PATH | tr ':' '\n' 으로 경로를 한 줄씩 분리해 어느 디렉토리가 먼저 검색되는지 순서를 확인한다
  • bash -c 'echo $MY_VAR' 의 출력이 비어 있으면 export 없이 선언한 것이다 — 동일 변수를 export 후 같은 명령을 실행하면 값이 출력된다. 이 두 결과의 차이가 지역 변수 vs 환경변수의 핵심이다
  • 새 터미널(비로그인 셸)에서 export 설정 변수가 사라지면 → ~/.bashrc에 기록되지 않은 것. .bashrc에 추가 후 source ~/.bashrc 하면 즉시 적용되고 이후 모든 새 터미널에서도 유지된다
$PATH 이해하고 수정하기

$PATH는 쉘이 명령어를 찾는 디렉토리 목록입니다. 콜론(:)으로 구분되며, 왼쪽에서 오른쪽 순서로 검색합니다.

로컬 터미널
# PATH 현재 값 확인
echo $PATH
# 출력: /usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin

# 보기 좋게 한 줄씩 출력
echo $PATH | tr ':' '\n'
# 출력:
# /usr/local/bin
# /usr/bin
# /bin
# /usr/local/sbin
# /usr/sbin

# 특정 명령어가 어디서 실행되는지 확인
which python3
# 출력: /usr/bin/python3

which java
# 출력: /usr/lib/jvm/java-17-openjdk/bin/java

# which가 없는 명령어는 PATH에 없다는 뜻
which myapp
# 출력: which: no myapp in (/usr/local/bin:/usr/bin:/bin:...)

PATH에 디렉토리 추가 — PATH 앞이나 뒤에 디렉터리를 추가해 명령어 검색 경로를 확장합니다:

로컬 터미널
# 현재 세션에서만 유효한 PATH 추가 (맨 앞에 추가 — 우선순위 높음)
export PATH="/opt/myapp/bin:$PATH"

# 확인
echo $PATH
# 출력: /opt/myapp/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin

# 맨 뒤에 추가 (우선순위 낮음 — 기존 명령이 있으면 기존 것 사용)
export PATH="$PATH:/opt/legacy/bin"

PATH 추가를 영구적으로 ~/.bashrc에 기록 — 재부팅 후에도 PATH가 유지되도록 설정 파일에 추가합니다:

로컬 터미널
# ~/.bashrc 파일 끝에 추가
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc

# 변경사항 즉시 적용
source ~/.bashrc

# 확인
echo $PATH | tr ':' '\n' | grep local
# 출력: /home/alice/.local/bin

type 명령으로 명령어 종류 확인 — 명령어가 실행 파일인지, alias인지, 내장 명령인지 구분합니다:

로컬 터미널
# which보다 더 많은 정보를 제공
type ls
# 출력: ls is aliased to `ls --color=auto'

type cd
# 출력: cd is a shell builtin

type python3
# 출력: python3 is /usr/bin/python3

type ll
# 출력: ll is aliased to `ls -alF'
source 명령어 — 로그아웃 없이 설정 적용

.bashrc를 수정한 후 로그아웃하지 않고 즉시 적용하는 방법이 source 명령입니다. . (점)source의 동의어입니다.

로컬 터미널
# ~/.bashrc를 수정했다면
nano ~/.bashrc
# (편집 후 저장)

# 방법 1: source 명령
source ~/.bashrc

# 방법 2: . (점) 명령 — 완전히 동일한 동작
. ~/.bashrc

# 방법 3: bash를 다시 실행 (새 프로세스 생성 — source와 다름)
exec bash   # 현재 쉘을 새 bash로 교체

source vs 새 쉘 실행의 차이source는 현재 쉘에서, bash script.sh는 자식 쉘에서 실행해 변수 전달 방식이 다릅니다:

로컬 터미널
# source는 현재 쉘 컨텍스트에서 실행
# → 지역 변수, 현재 디렉토리 등이 유지됨

export TEST_VAR="hello"
source ~/.bashrc    # TEST_VAR가 유지됨 (현재 쉘에서 실행)
echo $TEST_VAR
# 출력: hello

# bash 스크립트로 실행하면 자식 프로세스에서 실행
# → 환경변수 변경이 부모 쉘에 영향을 주지 않음
bash some-script.sh   # 자식 프로세스 실행, 부모 쉘에 영향 없음

source 실전 활용 패턴.env 파일 로드, 설정 파일 즉시 반영 등 현장에서 자주 쓰는 source 패턴입니다:

로컬 터미널
# 환경 설정 파일을 분리해서 관리
# ~/.bashrc 내용:
cat ~/.bashrc
# ...
# source ~/.bash_aliases    # alias 모음
# source ~/.bash_functions  # 함수 모음
# source ~/.bash_private    # 비밀 키 등 (git에 올리지 않음)

# 각 파일이 존재할 때만 읽도록 방어적으로 작성
if [ -f ~/.bash_aliases ]; then
    source ~/.bash_aliases
fi

특정 파일이 실제로 로드되고 있는지 디버그 — 설정 파일이 로드되는지 확인하고 로드 순서 문제를 진단합니다:

로컬 터미널
# ~/.bashrc 최상단에 임시로 추가해서 확인
# echo "~/.bashrc loaded at $(date)" >> /tmp/shell-debug.log

# 어떤 순서로 파일이 로드되는지 추적
bash --login -x 2>&1 | grep "source\|^\+" | head -30
alias 정의하고 영구 적용하기

alias는 긴 명령을 짧게 줄이는 쉘 기능입니다. 생산성에 직접적인 영향을 주므로 자신만의 alias 세트를 만드는 것이 중요합니다.

로컬 터미널
# 현재 세션에서 alias 정의
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias grep='grep --color=auto'

# alias 목록 확인
alias
# 출력:
# alias grep='grep --color=auto'
# alias l='ls -CF'
# alias la='ls -A'
# alias ll='ls -alF'

# alias 사용
ll /etc
# 출력:
# total 1084
# drwxr-xr-x. 141 root root  8192 Mar 26 09:15 ./
# drwxr-xr-x.  18 root root   235 Mar 10 14:22 ../
# -rw-r--r--.   1 root root    16 Mar 10 14:22 adjtime
# ...

# alias 삭제
unalias ll

실무에서 자주 쓰는 alias 모음 — 반복되는 긴 명령어를 짧게 줄이는 현장 alias 모음입니다:

로컬 터미널
# 안전 장치
alias rm='rm -i'        # 삭제 전 확인 요청
alias cp='cp -i'        # 덮어쓰기 전 확인
alias mv='mv -i'        # 이동 전 확인

# 디렉토리 이동
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'

# 자주 가는 디렉토리
alias proj='cd ~/projects'
alias logs='cd /var/log'

# 시스템 정보
alias df='df -hT'                    # 사람이 읽기 좋은 형식
alias du='du -sh'                    # 디렉토리 용량 요약
alias ps='ps auxf'                   # 트리 형태로 프로세스 표시
alias ports='ss -tulnp'              # 열린 포트 확인
alias myip='curl -s ifconfig.me'     # 외부 IP 확인

# Git 단축어
alias gs='git status'
alias ga='git add'
alias gc='git commit'
alias gp='git push'
alias gl='git log --oneline --graph --decorate'

alias를 영구적으로 저장하는 패턴 — alias를 설정 파일에 추가해 재부팅 후에도 유지합니다:

로컬 터미널
# ~/.bash_aliases 파일 생성 (관리하기 쉽도록 별도 파일로 분리)
cat > ~/.bash_aliases << 'EOF'
# 안전 장치
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# 탐색
alias ll='ls -alF --color=auto'
alias la='ls -A'
alias ..='cd ..'
alias ...='cd ../..'

# 시스템
alias df='df -hT'
alias ports='ss -tulnp'
alias myip='curl -s ifconfig.me'

# Git
alias gs='git status'
alias gl='git log --oneline --graph --decorate -20'
EOF

# ~/.bashrc에 자동 로드 추가
echo '' >> ~/.bashrc
echo '# alias 파일 로드' >> ~/.bashrc
echo 'if [ -f ~/.bash_aliases ]; then' >> ~/.bashrc
echo '    source ~/.bash_aliases' >> ~/.bashrc
echo 'fi' >> ~/.bashrc

# 즉시 적용
source ~/.bashrc

# 확인
alias rm
# 출력: alias rm='rm -i'
개인 스크립트 디렉토리를 PATH에 추가하기

자주 쓰는 스크립트를 어느 디렉토리에서든 명령어처럼 실행하려면, 스크립트가 위치한 디렉토리를 PATH에 추가해야 합니다.

로컬 터미널
# 개인 스크립트 디렉토리 생성
mkdir -p ~/bin

# 스크립트 예시 작성
cat > ~/bin/server-info << 'EOF'
#!/bin/bash
echo "=== 서버 정보 ==="
echo "호스트명: $(hostname)"
echo "IP 주소: $(hostname -I | awk '{print $1}')"
echo "OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)"
echo "커널: $(uname -r)"
echo "CPU 코어: $(nproc)"
echo "메모리: $(free -h | awk '/^Mem/{print $2}') 전체, $(free -h | awk '/^Mem/{print $7}') 사용 가능"
echo "디스크: $(df -h / | awk 'NR==2{print $2}') 전체, $(df -h / | awk 'NR==2{print $4}') 사용 가능"
echo "업타임: $(uptime -p)"
EOF

# 실행 권한 부여
chmod +x ~/bin/server-info

# ~/bin을 PATH에 추가 (이미 /etc/profile.d/가 추가한 경우도 있음)
# 현재 세션에서 테스트
export PATH="$HOME/bin:$PATH"

# 어느 디렉토리에서든 실행 가능한지 확인
cd /tmp
server-info

출력 예시:

=== 서버 정보 ===
호스트명: web-server-01
IP 주소: 192.168.1.100
OS: Red Hat Enterprise Linux 9.4 (Plow)
커널: 5.14.0-570.52.1.el9_6.x86_64
CPU 코어: 4
메모리: 7.6Gi 전체, 5.2Gi 사용 가능
디스크: 50G 전체, 35G 사용 가능
업타임: up 15 days, 3 hours, 42 minutes
로컬 터미널
# ~/.bashrc에 영구 등록
cat >> ~/.bashrc << 'EOF'

# 개인 스크립트 디렉토리
if [ -d "$HOME/bin" ]; then
    export PATH="$HOME/bin:$PATH"
fi

# ~/.local/bin도 있으면 추가 (pip install --user 등이 여기에 설치)
if [ -d "$HOME/.local/bin" ]; then
    export PATH="$HOME/.local/bin:$PATH"
fi
EOF

source ~/.bashrc

# PATH에 추가되었는지 확인
echo $PATH | tr ':' '\n' | grep -E "bin$"
# 출력:
# /home/alice/bin
# /home/alice/.local/bin

실무 — Java/Python/Node.js 버전 전환

PATH 해석과 버전 관리자 원리 — PATH는 콜론으로 구분된 디렉토리 목록이고 셸은 왼쪽부터 순차 탐색해 첫 매칭에서 멈춘다(which python이 그 경로). pyenv·nvm·sdkman은 자기 shims 디렉토리를 PATH 맨 앞에 prepend해 시스템 버전보다 먼저 발견되게 하고, shim이 선택된 버전으로 위임한다. 함정: 버전이 예상과 다르면 PATH 앞 dir 확인, sudo는 PATH를 초기화(secure_path)해 사용자 shims가 빠짐, PATH 위치가 우선순위를 정한다확대

💼
실무 맥락PATH 조작으로 언어 런타임 버전 전환하기
현업 패턴

실무에서는 프로젝트마다 다른 언어 버전이 필요한 경우가 많습니다. nvm, pyenv, sdkman 같은 도구들도 결국 내부적으로 PATH를 조작하는 방식으로 동작합니다. 그 원리를 직접 이해하면 어떤 도구든 트러블슈팅이 쉬워집니다.

원리: PATH 앞부분에 원하는 버전의 bin 디렉토리를 추가

PATH는 왼쪽에서 오른쪽으로 검색하므로, 맨 앞에 추가된 디렉토리가 항상 우선 실행됩니다.

로컬 터미널
# 현재 Java 버전 확인
java -version
# 출력: openjdk version "11.0.22" 2024-01-16
#        OpenJDK Runtime Environment (build 11.0.22+7)

# 시스템에 설치된 Java 버전들 확인
ls /usr/lib/jvm/
# 출력:
# java-11-openjdk-amd64
# java-17-openjdk-amd64
# java-21-openjdk-amd64

# Java 17로 전환 (현재 세션만)
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"
export PATH="$JAVA_HOME/bin:$PATH"

java -version
# 출력: openjdk version "17.0.10" 2024-01-16
#        OpenJDK Runtime Environment (build 17.0.10+7)

# ~/.bashrc에 영구 적용
cat >> ~/.bashrc << 'EOF'

# Java 환경 설정
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"
export PATH="$JAVA_HOME/bin:$PATH"
EOF

Python 버전 전환 (pyenv 원리 이해) — pyenv는 PATH 앞에 shim을 넣어 버전별 실행 파일을 전환합니다:

로컬 터미널
# pyenv를 설치하지 않고 수동으로 같은 원리 구현
# 여러 버전의 Python이 /opt/python/ 아래 설치되어 있다고 가정

ls /opt/python/
# 출력: 3.9.18  3.10.13  3.11.8  3.12.2

# Python 3.11 사용
export PATH="/opt/python/3.11.8/bin:$PATH"
python3 --version
# 출력: Python 3.11.8

# pyenv가 실제로 하는 일 확인 (pyenv 설치 시)
cat ~/.pyenv/shims/python3
# 실제로는 PATH 앞부분에 shims 디렉토리를 추가하고
# shim 스크립트가 올바른 버전으로 호출을 중계함

# pyenv 설치 시 ~/.bashrc에 들어가는 내용
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"    # pyenv가 PATH를 조작하는 함수 실행

Node.js 버전 전환 (nvm 원리) — nvm도 PATH를 조작해 활성화된 버전의 node를 먼저 찾도록 합니다:

로컬 터미널
# nvm 없이 수동으로 Node 버전 전환
ls /opt/node/
# 출력: v18.20.2  v20.12.0  v22.1.0

# Node 20 사용
export PATH="/opt/node/v20.12.0/bin:$PATH"
node --version
# 출력: v20.12.0

npm --version
# 출력: 10.5.0

# nvm 설치 시 ~/.bashrc에 들어가는 내용
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"   # nvm 로드
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

프로젝트별 자동 버전 전환 — .nvmrc 또는 .python-version 활용 — 프로젝트 디렉터리에 들어오면 지정된 버전으로 자동 전환합니다:

로컬 터미널
# 프로젝트 디렉토리에 버전 파일 생성
echo "20" > ~/projects/my-app/.nvmrc
echo "3.11" > ~/projects/ml-project/.python-version

# ~/.bashrc에 디렉토리 이동 시 자동 전환 함수 추가
cat >> ~/.bashrc << 'EOF'

# 디렉토리 이동 시 .nvmrc 자동 감지
cd() {
    builtin cd "$@"
    if [ -f ".nvmrc" ] && command -v nvm &>/dev/null; then
        nvm use --silent
    fi
}
EOF

버전 전환 확인 스크립트 — 현재 활성화된 Python/Node 버전과 PATH를 한 번에 확인합니다:

로컬 터미널
cat ~/bin/check-versions << 'EOF'
#!/bin/bash
echo "=== 현재 활성 런타임 버전 ==="
command -v java &>/dev/null && echo "Java:   $(java -version 2>&1 | head -1)"
command -v python3 &>/dev/null && echo "Python: $(python3 --version)"
command -v node &>/dev/null && echo "Node:   $(node --version)"
command -v npm &>/dev/null && echo "npm:    $(npm --version)"
echo ""
echo "=== 런타임 위치 ==="
command -v java &>/dev/null && echo "java:   $(which java)"
command -v python3 &>/dev/null && echo "python3: $(which python3)"
command -v node &>/dev/null && echo "node:   $(which node)"
EOF
chmod +x ~/bin/check-versions

check-versions
# 출력:
# === 현재 활성 런타임 버전 ===
# Java:   openjdk version "17.0.10" 2024-01-16
# Python: Python 3.11.8
# Node:   v20.12.0
# npm:    10.5.0
#
# === 런타임 위치 ===
# java:    /usr/lib/jvm/java-17-openjdk-amd64/bin/java
# python3: /opt/python/3.11.8/bin/python3
# node:    /opt/node/v20.12.0/bin/node

트러블슈팅

상황: git status를 실행하면 command not found가 납니다. 분명히 예전엔 됐는데 갑자기 안 되거나, 새 서버에서 처음 접속했을 때 발생합니다.

원인: (1) 프로그램이 설치되지 않음, (2) 설치는 됐지만 실행 파일 경로가 PATH에 없음, (3) 오타 — 세 가지 중 하나입니다. PATH가 .bashrc 오타로 오염되거나, 다른 도구가 PATH를 덮어쓴 경우에도 발생합니다.

진단: 설치 여부와 PATH를 단계별로 확인합니다.

로컬 터미널
# 1단계: 실행 파일이 시스템 어디에 있는지 확인
which git          # PATH 검색
find /usr -name "git" -type f 2>/dev/null
# /usr/bin/git  ← 설치는 됐는데 PATH에 없는 것

# 2단계: 발견된 경로로 직접 실행 (PATH와 무관하게)
/usr/bin/git --version
# git version 2.39.3  ← 실행 됨 = PATH 문제 확정

# 3단계: 현재 PATH에서 무엇이 빠져 있는지 확인
echo $PATH | tr ':' '\n'
# /usr/local/bin
# /home/alice/bin
# ← /usr/bin이 없음

# PATH 오염 원인 추적
grep -n "PATH" ~/.bashrc ~/.bash_profile ~/.profile 2>/dev/null

해결:

로컬 터미널
# 임시 복구 (현재 세션)
export PATH="/usr/bin:$PATH"
git status  # 이제 됨

# PATH가 완전히 망가진 경우 기본값으로 리셋
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin"

# .bashrc에서 문제 줄 수정 후 적용
nano ~/.bashrc
source ~/.bashrc

상황: .bashrc를 수정하고 source ~/.bashrc를 실행했더니 ls, cat, which 같은 기본 명령어까지 전부 command not found가 납니다. 터미널이 거의 사용 불가 상태가 됐습니다.

원인: export PATH="/opt/myapp" 처럼 $PATH를 빠뜨리고 경로를 완전히 덮어쓴 경우 발생합니다. 기존 /usr/bin, /bin 경로가 모두 날아가면서 시스템 명령어들을 찾을 수 없게 됩니다.

진단: 현재 PATH가 무엇인지 확인합니다.

로컬 터미널
# 현재 PATH 확인
echo $PATH
# /opt/myapp   ← /usr/bin, /bin이 없음

# .bashrc에서 문제 줄 찾기 (절대 경로 사용 - PATH 없이)
/usr/bin/grep -n "PATH" /home/$USER/.bashrc
# 45: export PATH="/opt/myapp"   ← $PATH 누락

해결:

로컬 터미널
# PATH 즉시 복구 (export는 bash 내장 명령이므로 PATH 불필요)
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin"

# 이제 기본 명령어 사용 가능해짐
grep -n "PATH" ~/.bashrc
# 45: export PATH="/opt/myapp"

# 문제 줄 수정
nano ~/.bashrc
# export PATH="/opt/myapp:$PATH"  ← $PATH 추가

source ~/.bashrc  # 적용

# 예방: .bashrc 수정 전 백업 습관화
cp ~/.bashrc ~/.bashrc.backup.$(date +%Y%m%d)
# 새 PATH 설정은 서브쉘에서 먼저 테스트
(export PATH="/opt/newapp/bin:$PATH"; newapp --version)

상황: 터미널에서 직접 ~/bin/deploy.sh를 실행하면 잘 되는데, crontab에 등록하고 자동으로 돌리면 항상 실패합니다. 로그에는 command not found가 찍혀 있습니다.

원인: cron은 매우 제한된 환경변수(PATH=/usr/bin:/bin, SHELL=/bin/sh)만 가집니다. 터미널에서 설정한 JAVA_HOME, PYENV_ROOT, NVM_DIR 등은 cron 환경에서 존재하지 않습니다.

진단: cron 실제 환경변수를 파일로 덤프해 확인합니다.

로컬 터미널
# crontab에 1회성 디버그 작업 추가
crontab -e
# * * * * * env > /tmp/cron-env.txt 2>&1

# 1분 후 확인
cat /tmp/cron-env.txt
# HOME=/home/alice
# LOGNAME=alice
# PATH=/usr/bin:/bin       ← /opt/maven/bin이 없음
# SHELL=/bin/sh            ← bash가 아닌 sh
# ← JAVA_HOME, MAVEN_HOME 모두 없음

# cron과 동일한 환경에서 스크립트 테스트
env -i HOME=$HOME LOGNAME=$USER PATH=/usr/bin:/bin SHELL=/bin/sh bash ~/bin/deploy.sh

해결:

로컬 터미널
# 방법 1 (권장): 스크립트 내에서 환경변수 명시적 선언
cat > ~/bin/deploy.sh << 'EOF'
#!/bin/bash
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"
export MAVEN_HOME="/opt/maven"
export PATH="$JAVA_HOME/bin:$MAVEN_HOME/bin:/usr/local/bin:/usr/bin:/bin"

cd /home/alice/projects/my-app || exit 1
mvn clean package -q >> /var/log/deploy.log 2>&1
EOF
chmod +x ~/bin/deploy.sh

# 방법 2: crontab 상단에 환경변수 선언
crontab -e
# SHELL=/bin/bash
# PATH=/opt/maven/bin:/usr/lib/jvm/java-17/bin:/usr/bin:/bin
# JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
# 0 2 * * * /home/alice/bin/deploy.sh >> /var/log/deploy.log 2>&1

# cron 로그 확인 (실행 자체가 안 될 때)
journalctl -u crond --since "1 hour ago"
grep CRON /var/log/syslog | tail -20

심화 — 파일은 바꿨는데 프로세스는 옛 값을 붙든다

💡개념

심화: 환경은 프로세스마다 복사된 스냅샷이다

지금까지는 "어느 파일에 쓰면 적용되나"를 다뤘습니다. 그런데 파일을 올바르게 고쳤는데도 이미 실행 중인 프로세스에는 그 변경이 통하지 않는 경우가 있습니다. 이 벽을 이해하려면 환경변수가 '살아 있는 공유 저장소'가 아니라 '프로세스마다 복사된 사본'이라는 사실을 알아야 합니다.

  • 환경은 exec 시점의 스냅샷입니다. 프로세스가 시작(fork 후 exec)될 때 부모의 environ을 통째로 복사해 자기 메모리에 들고 갑니다. 이후 부모가 값을 바꿔도 이미 뜬 자식에게는 반영되지 않고, 반대로 자식이 바꾼 값도 부모로 돌아가지 않습니다. 상태는 시작하는 순간 한 번 아래로만 복사됩니다.
  • 그래서 dotfile·/etc/environment를 고쳐도, 그 전에 시작된 셸·데몬·GUI 세션은 옛 값을 그대로 붙듭니다. 새 값은 "그 파일을 새로 읽고 시작한 프로세스"부터 보입니다. 방금 연 SSH 세션에선 새 값이 나오는데 오래된 데몬은 옛 값을 쓰는 불일치가 여기서 생깁니다.
  • 실행 중 프로세스의 실제 환경은 /proc/PID/environ에 있습니다. 추측 대신 증거로 확인하세요:
로컬 터미널
# 특정 프로세스가 지금 들고 있는 환경변수 (변수는 NUL로 구분됨)
cat /proc/$(pgrep -f myapp | head -1)/environ | tr '\0' '\n' | sort

# 내 셸 프로세스의 환경도 같은 방식으로 볼 수 있다
cat /proc/self/environ | tr '\0' '\n' | grep PATH
  • 반영시키려면 그 프로세스를 재시작해야 합니다. 실행 중 프로세스의 환경을 밖에서 안전하게 바꾸는 표준 방법은 없기 때문입니다. systemd 서비스면 유닛의 Environment=/EnvironmentFile=을 갱신한 뒤 systemctl daemon-reload && systemctl restart <서비스>. /etc/environment처럼 PAM이 로그인 시 1회 읽는 변수는, 이미 로그인된 세션과 그 자식에는 안 들어오므로 재로그인이 필요합니다.

정리하면, 환경변수 문제는 두 층입니다 — "어느 파일에 쓰나(적용 대상)"와 "언제 읽히나(스냅샷 시점)". 앞 절이 첫 번째 층이라면, 이 절의 스냅샷 개념이 두 번째 층입니다.

상황: /etc/environment(또는 서비스의 EnvironmentFile)에서 DB_HOST를 새 값으로 수정하고 저장했습니다. 그런데 오래 떠 있던 애플리케이션은 여전히 옛 DB로 붙습니다. 더 헷갈리는 건, 새 SSH 세션에서 echo $DB_HOST를 하면 새 값이 정상적으로 나온다는 점입니다. "파일도 맞고 셸에서도 새 값인데 왜 서비스만 옛날이지?"

원인: 그 서비스는 파일을 수정하기 전에 시작됐고, 시작 시점에 복사한 environ 스냅샷을 그대로 들고 있습니다. 파일을 나중에 바꿔도 이미 뜬 프로세스의 사본은 자동 갱신되지 않습니다. 새 셸에서 새 값이 보이는 건, 그 셸이 수정 후에 시작돼 파일을 새로 읽었기 때문입니다 — 서비스의 값과는 무관합니다.

진단: 그 서비스가 지금 실제로 들고 있는 값을 직접 확인합니다 — cat /proc/$(pgrep -f myapp | head -1)/environ | tr '\0' '\n' | grep DB_HOST. 여기서 옛 값이 나오는데 새 셸의 echo $DB_HOST는 새 값이면, "파일은 새 값, 프로세스는 옛 값"이라는 불일치가 확정됩니다. 이 대조가 원인을 못 박는 결정적 증거입니다.

해결: 값을 바꾼 뒤 해당 프로세스를 재시작해야 새 스냅샷을 뜹니다. systemd 서비스면 EnvironmentFile 갱신 → systemctl daemon-reloadsystemctl restart myapp 순서로. /etc/environment처럼 로그인 세션에 걸린 변수라면, 그 세션에서 뜬 프로세스는 재로그인(또는 서비스 재시작)해야 반영됩니다. sourceexport는 지금 이 셸과 앞으로의 자식에만 영향을 줄 뿐, 이미 따로 떠 있는 서비스에는 닿지 않는다는 점을 기억하세요.


고급 활용 — dotfiles 체계적으로 관리하기

새 서버에 접속할 때마다 alias를 다시 설정하고, PATH를 다시 추가하고, 프롬프트를 다시 꾸미는 상황이 반복된다면, dotfiles를 체계적으로 관리할 때입니다. .bashrc를 Git 저장소로 관리하면 어느 서버에서든 git clone 한 번으로 동일한 환경을 복원할 수 있습니다. 아래는 실무에서 바로 쓸 수 있는 .bashrc 구조와 Git 기반 dotfiles 관리 패턴입니다.

로컬 터미널
# 실무에서 권장하는 ~/.bashrc 구조
cat ~/.bashrc
로컬 터미널
#!/bin/bash
# ~/.bashrc — Alice의 쉘 설정
# 마지막 수정: 2026-03-26

# 1. 인터랙티브 쉘이 아니면 즉시 종료 (중요!)
case $- in
    *i*) ;;
      *) return;;
esac

# 2. 히스토리 설정
HISTCONTROL=ignoreboth    # 중복 및 공백으로 시작하는 명령 저장 안 함
HISTSIZE=10000            # 메모리에 저장할 히스토리 수
HISTFILESIZE=20000        # 파일에 저장할 히스토리 수
shopt -s histappend       # 쉘 종료 시 히스토리 파일에 추가 (덮어쓰지 않음)

# 3. 쉘 동작 설정
shopt -s checkwinsize     # 터미널 크기 변경 시 자동 업데이트
shopt -s globstar         # **/ 패턴 지원

# 4. PATH 설정
if [ -d "$HOME/bin" ]; then
    export PATH="$HOME/bin:$PATH"
fi
if [ -d "$HOME/.local/bin" ]; then
    export PATH="$HOME/.local/bin:$PATH"
fi

# 5. 개발 환경
export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"
export PATH="$JAVA_HOME/bin:$PATH"

export EDITOR="vim"
export VISUAL="vim"
export PAGER="less"

# 6. alias 로드
if [ -f ~/.bash_aliases ]; then
    source ~/.bash_aliases
fi

# 7. 프롬프트 설정 (PS1)
# \u = 사용자, \h = 호스트, \w = 현재 디렉토리
PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '

# 8. 자동완성
if ! shopt -oq posix; then
    if [ -f /usr/share/bash-completion/bash_completion ]; then
        source /usr/share/bash-completion/bash_completion
    fi
fi

dotfiles를 Git으로 관리하는 방법 — 설정 파일을 Git 저장소로 관리해 서버마다 일관된 환경을 유지합니다:

로컬 터미널
# dotfiles 저장소 초기화
mkdir -p ~/dotfiles
cd ~/dotfiles
git init

# 심볼릭 링크 방식으로 관리
cp ~/.bashrc ~/dotfiles/bashrc
ln -sf ~/dotfiles/bashrc ~/.bashrc

cp ~/.bash_aliases ~/dotfiles/bash_aliases
ln -sf ~/dotfiles/bash_aliases ~/.bash_aliases

# Git에 추가
cd ~/dotfiles
git add bashrc bash_aliases
git commit -m "초기 dotfiles 설정"

# GitHub에 올려두면 새 서버에서 바로 복원 가능
git remote add origin git@github.com:alice/dotfiles.git
git push -u origin main

새 서버에 dotfiles 설치 스크립트 — 새 서버에서 한 번의 실행으로 개인 환경 설정을 모두 적용합니다:

로컬 터미널
cat > ~/dotfiles/install.sh << 'EOF'
#!/bin/bash
# 새 서버에 dotfiles 설치

DOTFILES_DIR="$HOME/dotfiles"

echo "dotfiles 설치 시작..."

# 기존 파일 백업
for file in bashrc bash_aliases bash_profile; do
    if [ -f "$HOME/.$file" ] && [ ! -L "$HOME/.$file" ]; then
        mv "$HOME/.$file" "$HOME/.$file.backup.$(date +%Y%m%d)"
        echo "백업: ~/.$file → ~/.$file.backup.$(date +%Y%m%d)"
    fi
done

# 심볼릭 링크 생성
ln -sf "$DOTFILES_DIR/bashrc" "$HOME/.bashrc"
ln -sf "$DOTFILES_DIR/bash_aliases" "$HOME/.bash_aliases"
ln -sf "$DOTFILES_DIR/bash_profile" "$HOME/.bash_profile"

echo "설치 완료. 'source ~/.bashrc' 실행하세요."
EOF
chmod +x ~/dotfiles/install.sh

빠른 참고표

환경변수 관련 명령어 요약 — 자주 쓰는 환경변수 관련 명령어와 용도를 한눈에 정리했습니다:

명령어용도예시
export VAR=value환경변수 설정 및 내보내기export DEBUG=true
unset VAR변수 삭제unset DEBUG
printenv VAR특정 변수 값 출력printenv HOME
env모든 환경변수 출력env | sort
set변수 + 함수 모두 출력set | grep PATH
source FILE파일을 현재 쉘에서 실행source ~/.bashrc
. FILEsource의 단축형. ~/.bashrc
which CMD명령어 위치 확인which python3
type CMD명령어 종류 확인type ls
alias NAME='CMD'alias 정의alias ll='ls -alF'
unalias NAMEalias 삭제unalias ll
alias모든 alias 목록alias

dotfiles 로드 순서 요약 — 쉘 시작 모드별 설정 파일 로드 순서를 시각화합니다:

SSH 로그인 (Login Shell) — 순서대로 로드

  • /etc/environment — PAM이 읽음, 모든 로그인에 적용
  • /etc/profile — 시스템 전체 login shell 설정
  • /etc/profile.d/*.sh — 패키지별 시스템 설정
  • ~/.bash_profile — 사용자 login shell 설정 (보통 ~/.bashrc 호출)

새 터미널 탭 (Interactive Non-Login Shell)

  • /etc/bash.bashrc — 시스템 전체 interactive 설정
  • ~/.bashrc — 사용자 interactive 설정

스크립트 / cron (Non-Interactive, Non-Login)

  • 아무 설정 파일도 자동으로 읽지 않음! → 필요한 환경변수는 스크립트 내에서 직접 설정


명령어·단축키 빠른 참조

이 모듈에서 다룬 환경변수·dotfiles 명령을 실전 옵션과 함께 모았습니다.

명령어/단축키용도자주 쓰는 예
export변수를 자식 프로세스에 전달export PATH="/opt/app/bin:$PATH"
unset변수 제거(민감정보 소거)unset DB_PASSWORD
env / printenv환경변수 목록·단일 조회env | sort, printenv HOME
set지역변수·함수까지 전체 조회set | grep MY_VAR
echo $PATH | tr ':' '\n'PATH를 한 줄씩 확인검색 순서(왼→오) 파악
which / type명령 위치·종류 확인type ls(alias·builtin 구분)
source / .설정을 현재 셸에 즉시 적용source ~/.bashrc
alias / unalias명령 단축 정의·해제alias rm='rm -i'
~/.bashrc대화형 셸 개인 설정(alias·PATH)새 터미널마다 로드
~/.bash_profile로그인 셸 설정(보통 .bashrc 호출)[ -f ~/.bashrc ] && . ~/.bashrc
/etc/environment시스템 전역 KEY=VALUE(셸 문법 불가)JAVA_HOME=/usr/lib/jvm/...
/proc/PID/environ실행 중 프로세스의 실제 환경값tr '\0' '\n' < /proc/PID/environ

관련 모듈로 더 깊이:

다음 모듈에서는 프로세스 관리(Process Management)를 다룹니다 — ps, top, kill, nice, pgrep 등으로 실행 중인 프로세스를 조회하고 제어하는 방법을 배웁니다.

지식 확인

퀴즈 — 10문제

Q1

셸에서 `APP_ENV=production`을 선언한 뒤 Python 스크립트를 실행했더니 `os.environ.get('APP_ENV')`가 None을 반환합니다. 원인은?

Q2

SSH로 서버에 접속한 뒤 `.bashrc`에 `export MY_VAR=hello`를 추가했는데 반영이 안 됩니다. 터미널을 새로 열면 잘 됩니다. 현재 세션에 즉시 반영하는 방법과, SSH 로그인 시 이 변수가 로드되지 않는 근본 원인은?

Q3

배포 스크립트에서 임시로 설정한 `DB_PASSWORD` 환경변수를 스크립트 종료 전에 셸 환경에서 제거하려 합니다. 올바른 명령은?

Q4

서버에 Node.js 18 바이너리를 `/opt/node18/bin`에 설치했습니다. `node` 명령어를 어디서든 실행할 수 있게 PATH를 설정할 때, 기존 시스템 명령어가 깨지지 않도록 하는 올바른 방법은?

Q5

CI/CD 파이프라인에서 모든 빌드 에이전트에 동일한 `JAVA_HOME` 환경변수를 설정해야 합니다. 특정 사용자가 아닌 시스템 전체에 적용하되, 셸 문법 없이 단순 키=값 형태로 설정하는 파일은?

Q6

SSH로 로그인할 때는 ~/.bash_profile이 읽히고, 이미 로그인된 상태에서 새 터미널(서브셸)을 열 때는 ~/.bashrc가 읽히는 이유는?

Q7

[심화] /etc/environment에서 어떤 변수를 새 값으로 바꿨는데, 오래 실행 중이던 데몬은 여전히 옛 값을 씁니다. 새로 연 SSH 세션에서는 새 값이 보입니다. 이유는?

Q8

[심화] 설정 파일의 DB_HOST를 새 값으로 바꿨는데 실행 중인 서비스는 계속 옛 주소로 접속합니다. 그 서비스가 지금 실제로 들고 있는 값을 확인하고 반영하는 방법은?

Q9

[1급] bash 로그인 셸이 시작될 때 읽는 초기화 파일의 처리 순서로 옳은 것은?

Q10

[1급] 셸에서 VAR=hello 로 값을 지정하고 export하지 않았다. 이 변수의 성격으로 옳은 것은?

0 / 10 답변

🧪 실습으로 확인하기

새 서버 인수인계 — 처음 30분

초급

낯선 Linux 서버를 인수받았을 때 OS, 서비스, 로그를 빠르게 파악하는 루틴을 직접 수행한다.

30📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요