Bash란 무엇인가, 셸이란 무엇인가 — 스크립트를 쓰기 전에

이 글에서는 GNU Bash 매뉴얼 1.1 What is Bash?, 1.2 What is a shell?, 3.8 Shell Scripts를 따라 Bash의 정체, 셸의 이중 역할, 스크립트 실행 모델을 정리합니다.

이 글을 읽고 나면

  • Bash가 sh / ksh / csh / POSIX와 어떤 관계인지 설명할 수 있습니다.

  • 셸이 “명령 인터프리터 + 프로그래밍 언어”라는 점을 구분할 수 있습니다.

  • 대화형 셸과 스크립트(비대화형) 실행·shebang의 의미를 이해합니다.

Bash란 무엇인가?

Bash는 GNU 운영체제의 ​셸, 즉 명령어 언어 인터프리터입니다. 이름은 Bourne-Again SHell — 7th Edition Unix의 Bourne 셸(sh, Stephen Bourne)에 대한 말장난입니다.

Bash의 중요한 특징을 한눈에 정리하면 아래와 같습니다.

비교 대상

쉬운 설명

sh(기본 셸)

Bash는 예전 셸인 sh랑 거의 비슷하게 쓸 수 있지만, 명령어를 쉽게 쓰거나 프로그램처럼 다룰 수 있는 기능이 더 많아요.

ksh, csh(다른 유명 셸)

kshcsh에서 편리했던 기능도 가져왔어요. 쉽게 말해 좋은 건 다 흡수했다고 보면 돼요.

POSIX(표준)

“POSIX”라는 표준 규칙을 지키려고 해요. 그래서 다른 시스템에서도 Bash 스크립트를 잘 쓸 수 있어요.

​이식성

리눅스, 맥, 윈도우 등 거의 모든 운영체제에서 쓸 수 있도록 만들어졌어요.

실무에서 많이 하는 실수 중 하나는 스크립트 첫 줄(shebang)에 #!/bin/sh를 적어 두고, Bash에서만 동작하는 문법([[ ]], 배열, ${BASH_SOURCE} 등)을 함께 사용하는 거예요. 이렇게 하면 이 파일은 실제로 Bash 스크립트가 아니라, sh가 이해할 수 있는 파일이어야 해요. 만약 배포 환경에서 /bin/sh가 Bash가 아니라 dash 같은 다른 셸이라면, 스크립트가 바로 오류를 내고 멈춰버릴 수 있습니다.

셸이란 무엇인가?

Unix나 리눅스에서 "셸"은 단순히 명령어를 입력하는 도구가 아니라, 명령들을 모아 자동화하거나 새로운 동작을 만들어낼 수 있는 두 가지 얼굴을 가지고 있어요.

- 명령 인터프리터:
보통 터미널에 ls, grep, make와 같은 명령을 입력하면, 이 명령들을 받아 실행해주는 역할을 해요.

- 프로그래밍 언어:
그리고 이 셸은 변수, 분기(if), 반복(for/while), 함수 등을 지원해서, 여러 명령을 파일에 모아두면 ​하나의 새로운 명령처럼 쓸 수 있습니다.
즉, 스크립트 파일은 /bin에 있는 시스템 명령과 동등하게 취급되기도 해요.

셸은 본질적으로 “명령을 실행하는 매크로 프로세서”입니다.
사용자가 입력한 텍스트와 심볼(변수 등)을 확장해서 복잡한 동작을 만들어냅니다.

실무자가 꼭 알아야 할 셸의 개념

용어

설명

​대화형(Interactive)

직접 키보드로 명령을 입력하는 방식

​비대화형(Non-interactive)

파일이나 문자열에서 명령을 읽는 방식 (스크립트 실행)

​동기/비동기 실행

끝날 때까지 기다리는 명령 vs &로 백그라운드 실행

​내장 명령(Builtin)

cd, exec, break 등 셸이 내부적으로 제공 (외부 프로그램이 아님)

​대화형 전용 기능

job control, 줄 편집, history, alias 등 편의 UX 기능

​한눈에 정리하는 Bash 셸의 두 얼굴

Bash 셸은 그 자체로 "명령 인터프리터"이자, "실제 프로그래밍 언어" 역할까지 함께 해요.
즉, 아래 두 가지 관점이 모두 중요합니다:

  • ​명령어 인터프리터:
    사용자가 ls, cd, grep처럼 한 줄씩 입력한 명령을 읽고, 해석해 실행하는 도구입니다.

  • ​스크립트 언어:
    변수, 조건문, 반복문, 함수 등 프로그래밍 기능을 내장해서, 여러 명령을 모아놓으면 새롭게 "하나의 명령"처럼 만들 수 있습니다.

실제로 Bash는 sh, ksh, csh 같은 이전 셸의 장점을 물려받아, 현대 리눅스에서 표준처럼 쓰이며,
POSIX라는 규칙도 따르려 노력해요. 그래서 Bash로 짠 스크립트는 웬만한 유닉스 계열 시스템에서 거의 그대로 동작하지요.

Bash를 "명령어 실행의 매크로 프로세서이자, 파일로도 담아 쓸 수 있는 언어"라고 정리할 수 있어요.

아래 표는 현업에서 꼭 아는 것이 유용한 셸 개념을 성격별로 나눠 정리한 것입니다.

분류

주요 특징 및 예시

​대화형

명령 프롬프트에서 직접 명령을 입력(터미널). 줄 편집, 히스토리 지원

​비대화형

파일(.sh)에 명령 모아 자동 실행(스크립트). shebang(#!/usr/bin/env bash) 필수

​내장 명령

Bash 자체 기능. 예) cd, exit, echo, exec

​외부 명령

실제 실행 파일이나 프로그램. 예) /bin/ls, /usr/bin/grep

​동기/비동기

기본은 순차(동기)실행, 끝나지 않은 명령을 &로 백그라운드(비동기)

​확장/치환

변수($VAR), 명령치환($(…)), 산술($((…))) 등

실전에서는

  • ​스크립트(.sh) 파일 과

  • ​터미널 명령줄 이 모두 Bash 셸의 기능 위에 돌아가고 있다고 생각하시면 됩니다.

​예시:
아래는 Bash가 비대화형(스크립트) 모드에서 "누가 나를 실행했는지", "내 버전은 뭔지" 등을 출력하는 실제 코드입니다.

Bash

#!/usr/bin/env bash echo "=== script identity ===" echo "\$0 = $0" echo "BASH_VERSION = ${BASH_VERSION:-<unset — not bash?>}" echo "shell PID = $$" case $- in *i*) echo "mode = interactive" ;; *) echo "mode = non-interactive" ;; esac

​정리:
Bash의 본질은 "명령 처리 + 자동화 + 프로그래밍 언어"라는 점을 꼭 기억해두세요!

셸은 본질적으로 ​명령을 실행하는 매크로 프로세서 이다. 텍스트와 심볼을 확장해 더 큰 표현을 만든다.

Unix 셸은 두 가지 형태를 갖습니다.

  1. ​명령 인터프리터 — GNU/Unix 유틸리티를 사용자에게 연결합니다.

  2. ​프로그래밍 언어 — 그 유틸리티를 조합합니다. 명령을 담은 파일은 그 자체가 새 명령이 되고, /bin의 시스템 명령과 ​같은 지위 로 PATH에서 찾을 수 있습니다.

추가로 알아 둘 점입니다.

개념

의미

Interactive

키보드에서 입력을 받음

Non-interactive

파일이나 문자열에서 명령을 읽음 (일반 스크립트)

​동기 / 비동기

끝날 때까지 기다림 vs &로 병렬

Builtin

셸 내부 명령. cd·exec·break처럼 ​셸 자신 을 바꿔야 해서 외부 프로그램으로 둘 수 없는 것들이 있음

​대화형 전용 기능

job control, 줄 편집, history, alias — “언어”보다 UX

셸의 힘(과 복잡성)은 대부분 ​내장된 프로그래밍 언어 에서 옵니다. 변수, 제어 흐름, quoting, 함수가 그 뼈대입니다. 이후 시리즈 글이 바로 이 뼈대를 매뉴얼 순서대로 깎아 갑니다.

셸 스크립트란 무엇인가 (매뉴얼 3.8)

​셸 스크립트 는 셸 명령을 담은 텍스트 파일입니다.

Bash를 다음처럼 호출하면 (그리고 -c / -s가 아니면) Bash는 그 파일에서 명령을 읽고 실행한 뒤 종료합니다. 이 모드가 ​비대화형 셸 입니다.

Bash

bash filename arguments…

실제 실행 과정을 단계별로 좀 더 상세하게 살펴볼게요.

항목

상세 동작 설명

$0

​스크립트 파일 이름 이 저장됩니다. 즉, 내부적으로 bash filename arguments…로 실행하면 $0은 항상 "filename"으로 잡힙니다. 셸 자체 이름(bash)이 아니라, 사용자가 실행시키는 파일이 무엇인지 알려줍니다.

위치 파라미터 ($1, $2, …)

명령줄에서 넘긴 ​나머지 인자(argument) 들이 각각 $1, $2, …로 저장됩니다. 만약 인자를 주지 않았다면 해당 파라미터는 unset(설정 안 됨) 상태입니다. $#는 인자 개수를, $@/$*는 전체 인자 목록을 뜻합니다.

경로에 /가 없음

실행 명령에 /가 없다면(예: myscript.sh), ​우선 현재 디렉토리(./) 에서 해당 파일을 찾습니다. 여기서도 없을 경우에는 환경 변수 $PATH에 설정된 디렉토리들을 차례로 탐색합니다. 즉, 파일이 어디 있는지 알아서 찾아줍니다.

실행할 파일이 바이너리로 보이면

스크립트 파일이 텍스트가 아니라 바이너리(실행파일)처럼 보일 경우, Bash는 해당 파일을 ​스크립트로 간주하지 않고 실행하지 않습니다. 즉, 명확히 텍스트 포맷(쉐뱅이나 명령)이 아니라면 에러를 냅니다.

실제 동작은 다음과 같습니다.

  1. 사용자가 명령줄에 bash myscript.sh foo bar를 입력.

  2. Bash는 myscript.sh 파일에서 위에서 설명한 방식으로 명령을 읽고 해석.

  3. $0에는 myscript.sh, $1에는 foo, $2에는 bar가 셋팅.

  4. 만약 myscript.sh가 현재 폴더에 없으면, $PATH를 따라가며 탐색.

  5. 파일의 첫 부분이 실행 가능한 바이트코드/바이너리로 보이면, 명령 실행을 중단하고 에러를 표시.

이 동작 덕분에 스크립트 파일도 시스템 명령처럼 ​입력값·이름·인터프리터 동작 을 명확하게 분리해서 관리할 수 있습니다. 실전에서 $0와 위치 파라미터의 동작을 잘 이해하면, 스크립트의 재사용성과 안전성이 크게 높아집니다.

실행 비트를 켠 뒤 PATH에서 찾으면, 셸은 ​새 Bash 인스턴스 를 만들어 스크립트를 돌립니다. 즉 사용자가 입력한

Bash

filename arguments…

는 (해당 파일이 실행 가능한 셸 스크립트일 때) 사실상

Bash

bash filename arguments…

와 같습니다.

#! (shebang)

대부분의 Unix에서 스크립트 첫 줄이 #!로 시작하면, 그 뒤에 오는 인터프리터로 나머지 파일을 실행합니다.

Bash

#!/usr/bin/env bash

shebang

의미

#!/bin/bash

시스템 고정 경로의 bash

#!/usr/bin/env bash

$PATH에서 첫 bash (Homebrew 등)

#!/bin/sh

POSIX 셸로 해석될 수 있음 — Bash 전용 문법 금지

구형 Unix는 인터프리터 이름+인자를 32자로 자르는 경우가 있어, shebang에 인자를 여러 개 넣는 것은 이식성이 떨어집니다.

실행 예제

identify_shell.sh 스크립트는 "현재 실행 중인 것이 Bash 스크립트인지, 스크립트가 어떤 실행 모드(대화형/비대화형)로 동작 중인지"를 명확하게 보여줍니다. 실제로 아래와 같이 사용합니다.

Bash

chmod +x source/B-01-what-is-bash-shell/identify_shell.sh ./source/B-01-what-is-bash-shell/identify_shell.sh hello world

아래는 예제 스크립트 전체와 주요 라인별 설명입니다.

Bash

#!/usr/bin/env bash # B-01: identity of Bash / shell script vs interactive # Demonstrates shebang, $0, args, BASH_VERSION, interactive check. set -eu echo "=== script identity ===" echo "\$0 = $0" # (1) 현재 스크립트 이름 또는 경로를 출력합니다. echo "basename \$0 = $(basename -- "$0")" # (2) 스크립트 파일 이름만 추출합니다. echo "argc (\$#) = $# " # (3) 전달된 인자(argument) 개수 출력 if (($# > 0)); then printf 'args =' printf ' %q' "$@" # (4) 인자 목록을 안전하게 표시 printf '\n' fi echo echo "=== which Bash is running? ===" echo "BASH_VERSION = ${BASH_VERSION:-<unset — not bash?>}" # (5) Bash 버전 정보. unset이면 비Bash echo "BASH = ${BASH:-<unset>}" # (6) Bash 실행 경로 등 환경 정보 echo "shell PID \$\$ = $$" # (7) 현재 프로세스 ID echo echo "=== interactive? ===" # $- contains 'i' when the shell is interactive (manual: interactive shells) case $- in *i*) echo "mode = interactive" ;; # (8) $-에 i가 있으면 대화형 모드 *) echo "mode = non-interactive (typical for scripts)" ;; # (9) 그렇지 않으면 비대화형(스크립트) 모드 esac if [[ -n "${PS1-}" ]]; then echo "PS1 set = yes (often means interactive prompt)" # (10) PS1 프롬프트가 있으면 대화형 가능성 높음 else echo "PS1 set = no" # (11) 프롬프트 미설정 fi echo echo "ok — this file is a shell script (manual §3.8)."

​주요 라인별 설명
1–3: 실행 시 스크립트의 이름($0)과 인자(argument) 개수/내용이 어떻게 잡히는지 확인합니다.
5–6: Bash 해석기로 실행되는지(BASH_VERSION, BASH 변수) 명확하게 보여줍니다.
8–9: $- 옵션 문자열에 'i'(interactive)가 있는지로 대화형 모드 판별.
10–11: PS1 환경변수 존재 여부로 프롬프트가 활성화된 대화형 쉘인지 추가로 진단합니다.

이 예제는 "같은 스크립트 텍스트라도 어떻게 실행(직접 실행/source 등)하느냐에 따라 셸의 모드와 변수 동작이 달라진다"는 점을 실감하라는 의도입니다. 대화형으로 이 스크립트를 source한다면 $-i가 포함될 수도 있습니다.

헷갈리기 쉬운 부분

  1. macOS /bin/bash 3.2 — Linux CI의 Bash 5와 기능이 다릅니다. 스크립트 상단에서 BASH_VERSION을 확인하거나, shebang을 의도한 bash로 고정하세요.

  2. ​로그인/대화형 설정 파일 — 스크립트는 보통 .bashrc를 읽지 않습니다. PATH·alias를 스크립트가 가정하면 cron/CI에서 실패합니다.

  3. “터미널에서 되는 한 줄” ≠ 스크립트 — 대화형 편의(alias, history 확장)에 의존하지 마세요.

  4. Bash가 답이 아닌 경우 — 복잡한 자료구조·HTTP·JSON 중심 로직은 Python 등이 유지보수에 유리합니다.

한 줄 요약

Bash는 POSIX 표준을 따르는 Bourne 계열의 셸이며, 셸은 명령을 해석하고 실행하는 인터프리터이자 자체 프로그래밍 언어입니다. 스크립트란 이러한 셸 언어로 작성된 비대화형 자동화 프로그램을 의미합니다.

On this page