Operating System, OS/Linux
셸 사용하기(Bash)
curious week
2025. 10. 3. 20:10
학습 목표 정리
- 셸 기본 동작과 대표 종류를 이해하고, 로그인/로그아웃/셸 전환을 할 수 있다.
- 명령의 형식, 옵션/인수, man/--help 등 온라인 매뉴얼을 활용할 수 있다.
- 히스토리(history)와 자동완성(Tab), 역검색(Ctrl+R)을 숙달한다.
- 특수문자, 파이프/리다이렉션, 명령 치환, 따옴표 규칙, 수식/변수 확장을 설명하고 사용할 수 있다.
- 셸 변수/환경변수와 Bash 초기화 파일들을 구분해 설정을 적용할 수 있다.
1) 셸 개요
셸이란
- 셸(Shell): 운영체제(커널)와 사용자를 연결해 주는 명령 해석기입니다. GUI 없이도 시스템을 제어할 수 있습니다.
- 대표 셸: Bash(Bourne Again SHell), sh(Bourne), ksh(Korn), zsh, csh 등.
- 프롬프트 관례: 일반 사용자: $, 루트: #.
내 로그인 셸 확인/변경
# 현재 셸 실행 파일 경로
echo "$SHELL"
# 현재 프로세스 기준 셸 이름
ps -p $$
# /etc/passwd 에 기록된 로그인 셸 확인(현재 사용자)
getent passwd "$USER" | cut -d: -f7
# 로그인 셸 변경(다음 로그인부터 적용)
chsh -s /bin/bash # /bin/zsh 등도 가능
로그인/로그아웃/가상 콘솔
- 로그아웃: exit 또는 Ctrl+D
- TTY 전환(리눅스): Ctrl + Alt + F1~F6 (배포판에 따라 F7~F1로 GUI 복귀) 각각의 다른 사용자로 이용 가능
- 유저 아이디와 비밀번호 입력 후 쉘로 전환됨.
2) 셸 명령 사용법
명령의 형식
command [options] [arguments]
예시:
who # 인수 없이 실행
date "+%F %T" # 옵션과 인수
ls -lat # 짧은 옵션 묶기: -l -a -t
ls --all # 긴 옵션
chsh -s /bin/sh heeseong
내부 명령 vs 외부 명령
- 내부(builtin): cd, echo, pwd 처럼 셸에 내장.
- 외부(external): 파일로 존재(/bin/ls 등). 검색 경로는 환경변수 PATH.
echo "$PATH" # 실행 파일 탐색 경로
type cd # builtin 여부 확인
type -a ls # 어떤 경로가 쓰이는지 전부
which ls # PATH 상 첫번째 ls 경로
온라인 매뉴얼
man passwd # 기본 섹션(보통 1)
man 5 passwd # 섹션 5(파일 포맷)
ls --help # GNU 도구 대부분 지원
섹션 요약(암기 포인트): 1(명령), 5(파일형식), 8(관리자 명령), 나머지는 필요 시 확인.
3) 히스토리 & 자동완성
히스토리
history # 전체 기록
history 10 # 최근 10개
!! # 직전 명령 재실행
!n # 히스토리 번호 n 실행
!grep # 'grep'으로 시작한 최근 명령 실행
팁:
- HISTSIZE(메모리 기록 수), HISTFILESIZE(파일 기록 수), HISTCONTROL=ignoredups:ignorespace 등으로 품질 개선.
- 위험 명령 재실행 전 !n:p(print)로 미리보기:
!105:p # 105번 명령을 실행하지 않고 출력만
자동완성 & 역검색
- Tab 자동완성: 파일/명령/사용자 홈(~username), 변수($VAR) 등.
- 역검색: Ctrl+R → 일부 입력 → 계속 Ctrl+R로 이전 매칭 이동 → Enter 실행, →로 편집.
4) 명령의 연결과 확장
특수문자 핵심
- 백슬래시 \ : 이스케이프(특수 의미 제거)
- 틸드 ~ : 홈 디렉터리, ~user는 해당 사용자 홈
- 점 . : 현재 디렉터리 / .. : 상위 디렉터리 / . file= source file(현재 셸에서 실행)
- 해시 # : 주석(라인 끝까지)
- 달러 $ : 변수/확장 시작
- 앰퍼샌드 & : 백그라운드 실행
- 파이프 | : 표준출력 → 다음 명령 표준입력 (앞 명령의 출력을 다음 명령의 입력으로 연결시킴)
- 파일 입출력 결과를 리다이렉션: <, > (새로운 파일에 추가할 때), >> (기존 파일의 끝에 덧붙일 때), 2>, 2>>, &> 등
- 글로빙 * ? [] : 와일드카드 확장
- 느낌표 ! : 히스토리 확장(위 3장)
파이프라인
cat /etc/passwd | sort | less
grep -i "error" app.log | wc -l
리다이렉션(표준 스트림)
# 입력(표준입력)을 파일에서 가져오기: /etc/passwd 내용을 키보드 대신 sort 에 넣는다
sort < /etc/passwd
# stdout(표준출력)을 파일로 '덮어쓰기' 한다: 기존 typedef.out 내용은 사라짐
grep typedef /usr/include/* > typedef.out
# stderr(표준에러)만 별도의 파일로 보낸다: 에러 메시지만 error.txt에 저장
ls not_exist 2> error.txt
# stderr를 '추가(append)'로 보낸다: 기존 error.txt 뒤에 에러를 이어붙임
ls not_exist 2>> error.txt
# stdout을 all.txt로 보내고, stderr를 stdout과 합친다(둘 다 all.txt로 감)
cmd > all.txt 2>&1
# GNU bash 축약형: stdout+stderr를 한 번에 all.txt로 보냄(위와 동일 의미)
cmd &> all.txt
# 화면에도 출력하고 동시에 파일에도 저장: dmesg 출력이 터미널과 kernel.log 양쪽으로 복제됨
dmesg | tee kernel.log
명령 치환(가장 많이 씀)
- 권장: $( ... )
- 구식: `...` (중첩 불편)
echo "파일 개수: $(ls | wc -w)"
file "$(which bash)"
ls -l "$(command -v passwd)"
따옴표 규칙(실패/버그의 8할)
- 작은따옴표 '...': 확장 전부 비활성화(문자 그대로)
- 큰따옴표 "...": 변수/명령치환은 활성, 글로빙은 비활성
- 이스케이프 \: 문자 1개만 보호 (\$()는 치환이 일어나지 않음.)
echo "$(date)" # 치환 수행
echo "\$(date)" # 문자 그대로 $(date)
echo 'Today is $(date)' # 문자 그대로
산술 & 변수 확장
echo $((2025-1979)) # 46
echo "나는 $((10/2))살" # 5
echo "$BASH" # /usr/bin/bash 경로일 수도 있음(배포판에 따라 다름)
ls -l "$BASH"
5) 셸 변수와 환경설정
로컬 변수 vs 환경 변수
- 로컬 변수: 현재 셸에만 존재.
- 환경 변수: 자식 프로세스에 상속. export 필요.
NAME="KIM" # (로컬 변수) 현재 셸 안에서만 보이는 변수 생성
echo "$NAME" # (확인) 변수 값 출력 → KIM
FOO=bar # (로컬 변수) 우선 현재 셸에만 존재
export FOO # (환경변수로 승격) 이후 실행되는 하위 프로세스(자식 셸)에서도 보이게 함
sh -c 'echo "$FOO"' # (하위 셸 테스트) export 덕분에 sh에서도 FOO 값을 볼 수 있음 → bar
unset FOO # (변수 제거) 현재 셸에서 FOO 자체를 없앰(환경변수/로컬 둘 다 사라짐)
printenv | less # (환경변수 목록 보기) 전체 환경변수를 페이지로 넘겨 보기에 편함(위/아래 화살표, q로 종료)
# 추가 팁
export FOO=bar # (한 줄 축약) 로컬 생성 + export를 한 번에
export -n FOO # (언엑스포트) 환경변수 상태만 해제(로컬 변수로는 남김)
unset -v FOO # (변수 제거) -v는 변수, -f는 함수 제거
자주 쓰는 환경 변수(요점)
- PATH: 실행 파일 검색 경로
- HOME: 홈 디렉터리
- PWD: 현재 디렉터리
- USER: 사용자명
- SHELL: 로그인 셸 경로
- MAIL: 시스템 메일함 경로(배포판 따라 다름)
- PS1: 프롬프트 포맷
- HISTSIZE, HISTFILESIZE, HISTCONTROL: 히스토리 동작
Bash 초기화 파일(로그인/비로그인 구분)
- 로그인 셸: /etc/profile (모든 사용자에게 적용, 로그인할 때 가장 먼저 수행) → ~/.bash_profile (로그인 할 때 개별 사용자에게 적용) → ~/.bash_login → ~/.profile 중 첫번째 존재 파일만 읽음.
- 비로그인(대화형) 셸: /etc/bashrc(또는 /etc/bash.bashrc, 배포판별 // 모든 사용자에게 적요외고 셸을 시작할 때 마다 실행) → ~/.bashrc. (셸을 시작할 때 마다 실행, 개별 사용자에게 적용)
- 로그아웃 때: ~/.bash_logout. (로그아웃 시 실행)
- 권장 패턴: 사용자 설정은 ~/.bashrc 에 모으고, ~/.bash_profile에서 이를 source.
# ~/.bash_profile
# 로그인 셸에서 ~/.bashrc 도 불러오기
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# ~/.bashrc (예시 템플릿)
# 1) PATH 보강
export PATH="$HOME/.local/bin:$PATH"
# 2) 안전한 rm: 휴지통/확인 옵션 별칭
alias rm='rm -i' # -i: interactive(실수 방지)
# 3) 자주 쓰는 ls 별칭
alias ll='ls -alF' # -a(숨김) -l(상세) -F(/,*,@ 표시)
# 4) 히스토리 품질
export HISTSIZE=5000
export HISTFILESIZE=10000
export HISTCONTROL=ignoredups:ignorespace
# 5) 프롬프트(간단)
export PS1='\u@\h:\w\$ ' # 사용자@호스트:경로$
적용:
# 현재 셸에 바로 적용
source ~/.bashrc # 또는 . ~/.bashrc
실전 미니 실습(10분 컷)
- 명령 탐색/설명력 키우기
type -a ls
which rm
man 5 passwd
ls --help | less
- 히스토리/자동완성
history 5
!! # 직전 명령 재실행
!ls:p # 실행 전 미리보기
# Ctrl+R 로 'ssh' 검색 → Enter
- 파이프/리다이렉션 맛보기
grep -i bash /etc/passwd | wc -l
dmesg | tee dmesg.out | head
ls not_exist 2> err.txt
- 치환/따옴표/산술
echo "오늘은 $(date '+%F %T')"
echo '문자 그대로: $(date)'
echo "$((2**10))"
- 변수/환경/프로필
FOO=bar; export FOO
env | grep ^FOO=
echo 'alias gs="git status -sb"' >> ~/.bashrc
. ~/.bashrc
type gs
안전/디버깅 체크리스트
- rm, mv, cp 앞에는 항상 따옴표로 경로 감싸기: 공백/특수문자 안전.
- rm -rf "$TARGET_DIR"
- 글로빙 오동작 방지: 의도치 않은 * 확장 주의. 필요 시 따옴표로 보호.
- 옵션 종료 표식 -- 활용:
- rm -- -filename-starts-with-dash
- 파이프라인 디버깅: 중간 결과를 tee/head로 확인.
- set -u -o pipefail -e 등은 스크립트에서만 점진 도입(대화형 셸에는 과격할 수 있음).
- 권한 오류 시: sudo 필요 여부, 파일 소유자/퍼미션(ls -l, id, groups) 점검.
자주 틀리는 포인트 요약
- 작은따옴표 vs 큰따옴표 구분 실패 → 치환 필요하면 무조건 큰따옴표.
- which 남용 → type/command -v가 더 정확(alias/builtin까지 확인).
- ~/.bash_profile만 수정하고 ~/.bashrc를 안 읽음 → source 패턴 적용.
- !!/!string 오동작 → 실행 전 :p로 미리보기.
- PATH 덮어쓰기(PATH=...)로 시스템 경로 손실 → 항상 추가 방식:
- export PATH="$HOME/bin:$PATH"
암기용 치트시트
- 도움말: man CMD, man 5 FILETYPE, CMD --help
- 탐색: type CMD, command -v CMD, echo $PATH
- 히스토리: history, !!, !n, !str, Ctrl+R
- 파이프/리다이렉션: |, >, >>, 2>, &>, tee
- 치환/따옴표: $(...), '...'(그대로), "..."(확장)
- 산술: $(( expr ))
- 변수: NAME=val, export NAME, unset NAME, printenv
- 프로필 로드: ~/.bashrc ← ~/.bash_profile에서 source
- 안전옵션 예시: alias rm='rm -i', alias ll='ls -alF'
bash 셸 쓸 때 자주 쓰고 외워둬야하는 명령어
1) 디렉터리/파일 탐색
- ls (list directory) — 디렉터리 목록 보기
- ls -a : 숨김파일 포함(All)
- ls -l : 상세(Long)
- ls -al : 숨김+상세
- ls -h : 사람이 읽기 쉬운 크기(–human-readable, -l와 함께)
- ls -lt : 최신 수정순 정렬
- ls --color=auto : 색상(대부분 배포판 기본)
- 예시
- ls -alh
- ls -lt | head ← 최근 수정 10개 정도만 보고 싶을 때
- cd (change directory) — 디렉터리 이동
- cd : 홈으로
- cd - : 이전 디렉터리로
- cd .. : 상위 디렉터리로
- pwd (print working directory) — 현재 경로 표시
- 예시: pwd
- tree — 트리 형태로 보기(없으면 설치)
- tree -L 2 : 2단계까지만
- stat — 파일 메타데이터(타임스탬프, 권한 등)
- stat file.txt
- file — 파일 타입 판별(바이너리/텍스트 등)
- file my.bin
- which / type / command -v — 실행 파일/내장명령 확인
- type cd(builtin 여부), which ls, command -v grep
2) 내용 보기/프리뷰
- cat — 파일 출력(짧은 파일)
- cat file.txt
- less — 페이지 단위 뷰어(긴 파일)
- less /var/log/syslog ← q로 종료, /키워드 검색
- head / tail — 앞/뒤 일부
- head -n 20 file.log
- tail -n 100 file.log
- tail -f file.log ← 실시간 로그 추적
- wc (word count) — 줄/단어/바이트 수
- wc -l file.txt ← 라인 수
3) 검색/텍스트 처리(파이프라인의 핵심)
- grep (global regular expression print) — 문자열/정규식 검색
- grep -n : 줄번호
- grep -i : 대소문자 무시
- grep -R : 재귀 검색
- grep -E : 확장 정규식(ERE)
- grep -v : 부정(매칭 제외)
- grep -A 3 -B 2 : 앞뒤 문맥 출력
- 예시
- grep -Rni "TODO" src/
- dmesg | grep -i error
- find — 파일 탐색(조건/동작 조합)
- find . -name "*.log" : 이름
- find . -type f -size +100M : 100MB 초과 파일
- find . -mtime -1 : 24시간 이내 변경
- find . -maxdepth 1 -type d : 현재 깊이의 디렉터리만
- 안전한 실행(공백/특수문자 대응)
- find . -type f -print0 | xargs -0 grep -H "pattern"
- find . -type f -name "*.tmp" -delete
- find . -type f -exec chmod 644 {} + ← +는 배치 실행
- xargs — 표준입력을 인수로 변환
- -0 : 널 구분(공백 안전)
- -I{} : 자리표시자
- 예시
- printf "%s\0" *.jpg | xargs -0 -I{} mv "{}" images/
- sort / uniq — 정렬/중복 처리
- sort -n : 숫자 정렬, -r : 내림차순, -kN : N번째 필드 기준
- uniq -c : 중복 개수
- 예시
- sort access.log | uniq -c | sort -nr | head
- cut / tr — 필드/문자 변환
- cut -d',' -f1,3 file.csv : 1,3열 추출
- tr -d '\r' < in.txt > out.txt : CR 제거
- tr '[:lower:]' '[:upper:]'
- sed (stream editor) — 치환/삭제/추출
- sed -n '1,10p' file : 1~10줄 출력
- sed -E 's/(foo)+/bar/g' file : 정규식 치환
- 인플레이스 편집(GNU)
- sed -i 's/DEBUG/INFO/g' app.conf
- 백업 만들며 편집
- sed -i.bak 's/8080/80/' nginx.conf
- awk — 컬럼 처리/집계(에이더·웨인버그·커니핸 이름 앞글자)
- 구분자 지정: -F','
- awk -F, '{sum+=$3} END{print sum}' sales.csv
- awk '{print NR, $0}' file : 줄번호와 함께 출력
- tee — 출력 복제(화면+파일)
- make | tee build.log
- cmd | tee -a append.log
4) 파일/디렉터리 조작
- mkdir — 디렉터리 생성
- mkdir newdir
- mkdir -p a/b/c : 상위까지 생성
- rm — 파일/디렉터리 삭제(주의)
- rm file
- rm -r dir : 재귀 삭제
- rm -rf dir : 강제(매우 위험, 경로 항상 따옴표)
- 습관: alias rm='rm -i'로 확인 프롬프트
- cp — 복사
- cp src dst
- cp -r dir1 dir2 : 디렉터리 재귀
- cp -a : 속성 보존(archive)
- mv — 이동/이름 변경
- mv a.txt b.txt
- mv file /tmp/
- ln — 링크
- ln file link : 하드링크
- ln -s target symlink : 심볼릭 링크
5) 권한/소유/마스크
- chmod — 퍼미션 변경
- chmod 644 file : rw-r--r--
- chmod u+x script.sh : 실행권한 추가
- chmod -R 755 dir/ : 재귀
- chown — 소유자/그룹 변경
- chown user:group file
- chown -R user:group dir/
- umask — 기본 권한 마스크 확인/설정
- umask / umask 022
6) 디스크/용량
- df — 파일시스템 사용량
- df -h : 사람이 읽기 쉬운 단위
- du — 디렉터리별 용량
- du -sh * : 현재 디렉터리 하위 항목 요약
- du -sh .[!.]* * : 숨김 포함
- lsblk — 블록 디바이스 트리
- lsblk -f : 파일시스템/UUID 포함
- blkid — 블록 디바이스 식별 정보
- mount / umount — 마운트/해제
- mount | grep /dev/sd
- sudo umount /mnt/usb
- sync — 디스크에 버퍼 플러시
7) 압축/아카이브
- tar (tape archive) — 아카이브/해제
- tar -czf out.tgz dir/ : 압축 생성(gzip)
- tar -xzf out.tgz : 압축 해제
- tar -tf out.tgz : 목록만 보기
- gzip / bzip2 / xz
- gzip -k bigfile : 원본 유지(-k)
- xz -T0 hugefile : 멀티스레드 압축
- zip / unzip
- zip -r site.zip site/
- unzip site.zip -d dest/
8) 프로세스/서비스/로그
- ps (process status) — 프로세스 목록
- ps aux | grep nginx
- ps -ef : 다른 표기법(배포판 취향)
- top / htop — 실시간 모니터(htop은 설치형)
- top / htop
- pgrep / pkill — 이름 기반 찾기/종료
- pgrep -a node
- pkill -f "gunicorn: master"
- kill — PID로 종료
- kill -TERM 1234
- kill -KILL 1234 : 강제(SIGKILL)
- nice / renice — 우선순위 조정
- systemctl (systemd) — 서비스/부팅 관리
- systemctl status nginx
- sudo systemctl start|stop|restart nginx
- sudo systemctl enable|disable nginx
- journalctl — 시스템 로그
- journalctl -u nginx : 유닛별
- journalctl -u nginx -f : tail 모드
- journalctl --since "1 hour ago"
9) 네트워크/진단/전송
- ip (internet protocol) — 네트워크 구성
- ip a : 주소
- ip r : 라우팅
- ip -br a : 요약
- ss — 포트/소켓 확인
- ss -tulpn : 리스닝 TCP/UDP+프로세스
- ping / traceroute — 연결/경로
- ping -c 4 8.8.8.8
- traceroute example.com(설치형일 수 있음)
- dig / nslookup — DNS 조회
- dig +short A example.com
- dig TXT _acme-challenge.example.com
- curl — HTTP/FTP 등 다목적 전송
- curl -I https://example.com : 헤더만
- curl -fsSL https://... | bash : 설치 스크립트(주의)
- curl -o out.bin URL
- wget — 다운로드 도구(설치형일 수 있음)
- wget -O out.bin URL
- scp (secure copy, SSH) — 원격 복사
- scp file user@host:/path/
- scp -r dir user@host:/path/
- rsync — 동기화(증분/재시도)
- rsync -av --delete src/ user@host:/dst/
- ssh (secure shell) — 원격 접속
- ssh user@host
- ssh -i ~/.ssh/id_ed25519 user@host
10) 사용자/권한/계정
- whoami — 현재 사용자
- id — UID/GID/그룹
- groups — 소속 그룹
- sudo — 권한 상승
- sudo -v : 캐시 갱신
- sudo -k : 캐시 폐기
(계정 생성/변경은 배포판별 정책이 있어 필수만 기억: useradd, usermod, passwd 등)
11) 시간/환경/셸 유틸
- date — 날짜/시간
- date '+%F %T'
- date -d 'yesterday' '+%F' : 어제(gnu date)
- cal — 달력
- cal -y : 연간
- env / printenv — 환경변수
- export / unset — 변수 설정/해제
- export PATH="$HOME/.local/bin:$PATH"
- alias / unalias — 별칭
- alias ll='ls -alF'
- history — 히스토리
- history, !!(직전 명령 실행), !$(직전 마지막 인수), !^(직전 첫 인수), !해당번호 (해당 번호의 명령 실행), !해당문자열 (문자열로 시작하는 최근 명령 실행)
- 단축키(읽어두면 생산성 급상승)
- Ctrl+A/E : 줄 맨앞/맨뒤
- Alt+B/F : 단어 단위 이동
- Ctrl+U/K/W : 앞/뒤/단어 삭제
- Ctrl+R : 히스토리 역검색
- 작업 제어
- Ctrl+Z : 일시중지
- jobs / bg / fg
- nohup cmd & : 터미널 끊겨도 계속
- 터미널 멀티플렉서(필수 툴)
- tmux / screen : 세션 유지/분할(설치형)
12) “진짜 자주 쓰는 암기 세트”(초간단 20선)
- ls -alh
- cd - / pwd
- grep -Rni "text" .
- find . -type f -name "*.log" -delete
- sort | uniq -c | sort -nr | head
- cut -d, -f1,3 file.csv
- sed -i 's/foo/bar/g' file
- awk -F, '{sum+=$3} END{print sum}' file.csv
- du -sh * | sort -h
- df -h
- tar -czf out.tgz dir/ / tar -xzf out.tgz
- ps aux | grep proc / pgrep -a proc
- kill -TERM PID / pkill -f pattern
- systemctl status nginx / journalctl -u nginx -f
- ip a / ss -tulpn
- curl -I https://example.com
- ssh user@host / scp file user@host:/path/
- alias ll='ls -alF'
- history | tail / !! / !$
- nohup long_task & / tmux
용어 확장
- pwd = print working directory
- grep = global regular expression print
- sed = stream editor
- awk = Aho–Weinberger–Kernighan(저자 이름)
- ps = process status
- tar = tape archive
- ssh/scp = secure shell / secure copy