셸의 기능과 종류
셸의 기능
- 셸은 사용자와 커널 사이에서 중계자 역할을 수행하는 프로그램
셸의 종류
본 셸 (Bourne shell)
단순하고 처리 속도가 빠른 이유로 많이 사용됨
시스템 관리작업을 수행할 때 많은 스크립트는 본 셸을 기반으로 사용
sh 명령 사용
C 셸 (C shell)
본 셸의 기능 확장
에일리어스, 히스토리와 같은 사용자 편의 기능이 추가되어 제공됨
셸 스크립트 작성의 문법 형식이 C 언어와 비슷함
크기가 커지고 처리 속도가 느린 단점 등의 이유로 배시 셸에 밀림
csh 명령 사용
콘 셸 (Korn shell)
본 셸과의 호환성 및 편의 기능을 제공하면서 속도가 빠름
우분투 리눅스에서는 별도로 콘 셸을 설치하여 사용
ksh 명령 사용
배시 셸 (bash shell)
본 셸을 기반으로 개발된 셸, 본 셸과의 호환성을 유지하면서 C 셸, 콘 셸의 편리한 기능까지 제공
GPL(General Public License)을 따르는 공개 소프트웨어, 리눅스의 기본 셸로 제공 (우분투 리눅스에서도 O)
bash 명령 사용
대시 셸 (dash shell)
본 셀을 기반으로 개발됨, 포직스(POSIX) 표준을 준수하여 보다 작은 크기로 개발된 셸
부팅 시 셸 스크립트를 빠르게 실행시키며, 파일 크기가 작고 신뢰성이 높아 우분투 6.10 버전부터는 대시 셸을 시스템 기본 셸로 사용함
셸 스크립트 환경 변수
배시 셸의 주요한 환경변수
환경변수 의미 환경변수 의미
| 환경변수 | 의미 | 환경변수 | 의미 |
| HOME | 현재 사용자의 홈 디렉터리 | PATH | 실행 파일 찾는 경로 |
| LANG | 기본적으로 지원되는 언어 | PWD | 사용자의 디렉터리 위치 |
| TERM | 로그인 터미널 타입 | SHELL | 로그인에서 사용하는 셸 |
| USER | 현재 사용자의 이름 | DISPLAY | X 디스플레이 이름 |
| COLUMNS | 현재 터미널의 컬럼 수 | LINES | 현재 터미널 라인 수 |
| PS1 | 1차 명령 프롬프트 변수 | PS2 | 2차 명령 프롬프트(>) |
| BASH | bash 셸의 경로 | BASH_VERSION | bash 버전 |
| HISTFILE | 히스토리 파일의 경로 | HISTSIZE | 히스토리 파일에 저장 개수 |
| HOSTNAME | 호스트 이름 | USERNAME | 현재 사용자 이름 |
| LOGNAME | 로그인 이름 | LS_COLORS | ls 명령의 확장자 색상 |
| 메일을 보관하는 경로 | OSTYPE | 운영체제 타입 |
cf. 변수를 출력할 때 $를 붙여야 함
echo $HOME : 사용자의 홈 디렉터리 확인
echo $BASH_VERSION : bash 버전 확인
셸 변수 설정
사용자가 지정한 이름으로 설정할 수 있음
=을 사용하여 선언할 때 변수 이름과 문자열 사이에 공백이 존재해서는 안 됨
대/소문자 엄격하게 구별
변수 이름=문자열
ex) INSA=Hello
echo INSA : 변수명이 아닌 문자열로 취급하여 INSA가 출력됨
echo $INSA : 변수에 대입한 문자열인 Hello가 출력됨
환경변수 설정 명령 : export
먼저 셸 변수를 정의하고 export 명령을 사용하여 설정된 환경변수를 변경할 수 있음
‘export 환경변수=값’ 과 같이 선언할 수 O
export [옵션] [셸 변수] : 지정한 셸 변수를 환경변수로 변경하여 설정
옵션
-n : 환경변수를 셸 변수로 변경
cf. 환경변수 확인 : env | grep 변수명
export INSA : 셸 변수 INSA를 환경변수로 변경
export SPACE=key : 셸 변수를 선언하면서 곧바로 환경변수로 한번에 등록
환경변수를 셸 변수로 변경 : export -n
환경변수로 등록했던 셸 변수를 다시 셸 변수로 변경
export -n 환경변수
ex) export -n SPACE
셸 변수 해제 : unset
이미 정의된 셸 변수를 해제
unset 변수명
unset을 하면 echo $변수명 을 해도 아무 값이 출력되지 X
문제 12-01
- 셸 변수 DEPT를 선언하고 문자열 database를 대입하기
- DEPT 변수에 대입된 문자열 출력하기
- DEPT 변수를 환경변수로 전환하기
- 환경변수에 등록된 정보 출력하기
- 환경변수로 전환된 DEPT 변수를 다시 셸 변수로 전환하기
- 등록된 DEPT 셸 변수 해제하기
$ DEPT=database
$ echo $DEPT
$ export DEPT
$ env (혹은 쉽게 찾기 위해 env | grep DEPT)
$ export -n DEPT
$ unset DEPT
셸 스크립트의 특징
셸 출력 명령
공통 셸 출력 명령 : echo
모든 셸 스크립트 프로그래밍에서 공통으로 사용할 수 있는 출력 명령
echo [옵션] [문자열] : 화면에 한 줄의 문자열을 출력
옵션
-n : 문자열 중간에 선언하게 되면 선언한 위치에서 줄 바꿈을 수행
new line을 넣지 말아달라는 의미임 (아래 예시 참고)
-n을 어느 위치에 선언하느냐에 따라 출력결과가 다르게 나타날 수 있음
문자열 사이에 공백이 존재할 경우 문자열을 큰따옴표로 묶어줘야 함
ex) echo “I Love Ubuntu”
echo -n Nice : 옵션 지정으로 프롬프트 전에 문자열이 출력됨
NIce유저명@ubuntu:~$ ← 이런식으로 출력됨
출력형식 지정 명령 : printf
출력형식을 %d 지시자와 \n 줄바꿈 문자 등 C 언어에서 사용하는 출력함수인 printf() 함수의 형식을 지정하여 출력할 수 있음
printf [옵션] [문자열] : 출력형식을 지정하여 문자열을 출력
옵션
%d, \n 등 C언어의 printf()함수 형식을 지정
printf SPACE : 프롬프트 앞에 문자열이 출력됨 (SPACE유저명@ubuntu:~$)
printf “I Love \n Ubuntu” : Ubuntu를 다음 행으로 줄을 바꿔 출력 (두번째 줄: Ubuntu유저명@ubuntu:~$)
printf “%d + %d = %d \n” 30 50 80 : 30 + 50 = 80 출력
셸 스크립트 프로그래밍
셸 스크립트 작성과 실행
- gedit을 사용하여 셸 스크립트 프로그래밍 수행
- /sh_test.d : 셸 스크립트 파일을 저장할 디렉터리 생성 (디렉터리 명은 자유)
- .sh : 셸 스크립트 파일임을 쉽게 구별하기 위해 확장자 선언 (확장자 선언은 자유)
셸 스크립트 작성 후 sh 명령으로 실행하기
gedit 또는 vi 에디터를 사용하여 작성
sudo mkdir /sh_test.d
cd /sh_test.d
sudo gedit myname.sh
#! /bin/sh
echo " Name Print "
echo ">> Connect Name : " $USERNAME
exit 0
#! : Shebang(셔뱅)이라고 함, 인터프리터 경로를 나타냄
#! /bin/sh : bash를 사용하는 의미 (생략하면 안 됨)
echo : 문자열 출력
$USERNAME : 현재 시스템에 접속된 사용자 이름을 출력하는 환경변수 선언
exit 0 : 종료 코드 (0은 성공 의미)
sh myname.sh : 셸 스크립트 파일 실행
변수 선언
- 변수에 처음 값이 할당되면 변수는 자동으로 생성되므로 따로 변수를 선언하지 않음
- 셸에서 사용하는 변수는 모두 문자열(String)으로 취급되므로 숫자 또한 문자열로 처리됨
- 알파벳 대/소문자를 엄격하게 구별하며 변수의 값을 대입할 때는 ‘=’ 의 좌우에 공백이 존재해서는 안 됨
var1 = HI ← 오류: ‘=’ 좌우에 공백 있음
var2=good
var3=Nice day ← 오류: 두 개의 문자열인 경우 큰따옴표로 묶어야 함
var4=”Good morning”
var5=88+95 ← 오류는 없지만 연산은 안 됨(모두 문자열로 취급됨)
대입하는 값 사이에 공백이 있을 경우 반드시 큰따옴표로 묶기
변수에 값을 대입할 경우 이를 변수로 받기 위한 방법은 ‘$변수명’ 과 같이 변수명 앞에 $를 붙여주기
(변수임을 알리려고)
변수의 값에 공백 존재하지 않으면 $변수명, “$변수명” 상관 X
공백이 존재하면 무조건 “$변수명” 사용
변수의 입력과 출력
cd /sh_test.d
sudo gedit inout.sh
#! /bin/sh
echo " Q. Input : "
read input_string
echo " A. Output : $input_string "
exit 0
read input_string : 키보드로 입력한 값을 변수 input_string에 저장하는 read 명령
숫자 계산
키워드 expr을 사용해야 함
역따옴표(`)와 expr을 공백 없이 붙여서 사용해야 함, 역따옴표로 expr 연산식과 같이 시작과 끝을 묶어줘야 함
cf. 연산식에서 괄호를 사용하려면 괄호 앞에 \를 반드시 붙여줘야 함
사칙연산(+, -, , /) 중에서 예외적으로 곱셈 연산() 앞에도 반드시 \를 붙여줘야 함
sudo gedit arithmetic.sh
#! /bin/sh
echo " >> first : "
read a
echo " >> second : "
read b
echo " >> a = $a, b = $b "
add=`expr $a + $b`
gob=`expr $a \\* $b`
na=`expr $a / $b`
avg=`expr $add / 2`
echo " a + b = $add \\n a * b = $gob \\n a / b = $na \\n (a+b)/2 = $avg "
exit 0
sh arithmetic.sh : 셸 스크립트 실행
파라미터 변수
자신이 실행한 명령어의 파라미터(매개변수)를 의미함
$0, $1, $2, … 등과 같이 실행하는 명령의 부분을 각각 하나씩 변수로 지정
ex) dnf -y install xinetd 명령을 실행한다고 가정할 때 파라미터 변수
| 구분 | 수행할 명령 | 파라미터1 | 파라미터2 | 파라미터3 |
| 명령어 | dnf | -y | install | xinetd |
| 파라미터 변수 | $0 | $1 | $2 | $3 |
| 표현 방법 | $0 ← dnf | $1 ← -y | $2 ← install | $3 ← xinetd |
sudo gedit mapping.sh
#! /bin/sh
echo " >> One : $0 "
echo " >> Two : $1 "
echo " >> Three : $2 "
echo " >> Total : $* "
exit 0
echo “ >> Total : $* “ : 전체 파라미터 출력 (*는 전체를 의미)
sh mapping.sh 35 87 text_string
cf. text string 처럼 공백을 넣고 싶을 때 “text string” 입력, 큰따옴표 없이 입력하면 별개의 단어로 취급
문제 12-02
- 셸 스크립트 프로그램 test_1302.sh 작성하기
- 두 개의 변수 su1, su2를 선언하기
- su1 변수에 키보드로 23을 입력하여 저장하기
- su2 변수에 키보드로 56을 입력하여 저장하기
- 두 수의 곱을 변수 gob에 저장하기
- 키보드로 입력받은 값 출력하기
- 두 수의 곱셈 연산과 결과값 출력하기
$ gedit test_1302.sh
//셸 스크립트
#! /bin/sh
echo "1. 첫 번째 정수 입력"
read su1
echo "2. 두 번째 정수 입력"
read su2
echo ">> 두 수의 곱셈연산 결과"
gob=`expr $su1 \\* $su2`
echo " $su1 * $su2 = $gob "
exit 0
$ sh test_1302.sh
조건문과 관계 연산자
기본 if 문
주어진 조건이 참일 경우에만 수행하는 분기문으로 거짓일 경우에는 해당 명령을 수행하지 X
조건문을 묶는 대괄호 [] 안에 조건식을 선언할 때 각 단어와 연산자 사이에는 반드시 공백이 존재해야 함
1. 단일 조건 (if ~ then ~ fi)
if [ 조건식 ]; then
명령
fi
또는
if [ 조건식 ]
then
명령
fi
2. 이분 조건 (if ~ then ~ else ~ fi)
if [ 조건식1 ]; then
명령1
else
명령2
fi
cf. 1번처럼 ;를 쓰지 않고 then을 다음 줄로 보낼 수 있음
3. 다중 조건
if [ 조건식1 ]; then
명령1
elif [ 조건식2 ]; then
명령2
else
명령3
fi
(이때 elif는 여러 개 올 수 있음)
기본 if문 예시
sudo gedit basicif.sh
#! /bin/sh
if [ "space" = "space" ]
then
echo ">> compare : space = space ?? "
echo ">> result : True "
fi
exit 0
sh basicif.sh
echo “>> compare : space = space ?? “ : 여기서 물음표는 특별한 의미 없음
if~else문 예시
sudo gedit ifelse_01.sh
#! /bin/sh
echo ">> compare : space != space ?? "
if [ "space" != "space" ]
then
echo ">> result : True "
else
echo ">> result : False "
fi
exit 0
sh ifelse_01.sh
False가 출력될 것
비교 연산자
문자열 비교 연산자
| 연산자 | 의미 | 사용 예 | 결과 |
| = | 같음 | “문자열1” = “문자열2” | 두 문자열이 같으면 참 |
| != | 같지 않음 | “문자열1” != “문자열2” | 두 문자열이 같지 않으면 참 |
| -n | Null이 아닌 값 | -n “문자열” | 문자열이 빈 문자열이 아니면 참 |
| -z | Null 값 | -z “문자열” | 문자열이 빈 문자열이면 참 |
산술 비교 연산자
| 연산자 | 의미 | 사용 예 | 결과 |
| -eq | 같음 | 변수1 -eq 변수2 | 변수1과 변수2가 같으면 참 |
| -ne | 같지 않음 | 변수1 -ne 변수2 | 변수1과 변수2가 같지 않으면 참 |
| -gt | 큼 (초과) | 변수1 -gt 변수2 | 변수1이 변수2보다 크면 참 |
| -ge | 크거나 같음 (이상) | 변수1 -ge 변수2 | 변수1이 변수2보다 크거나 같으면 참 |
| -lt | 작음 (미만) | 변수1 -lt 변수2 | 변수1이 변수2보다 작으면 참 |
| -le | 작거나 같음 (이하) | 변수1 -le 변수2 | 변수1이 변수2보다 작거나 같으면 참 |
| ! | 부정 | !변수1 | 변수1이 아니면 참 |
예제
sudo gedit ifelse_02.sh
#! /bin/sh
echo " >> compare : 300 -gt 800 ?? "
if [ 300 -gt 800 ]
then
echo " >> result : True "
else
echo " >> result : False "
fi
exit 0
sh ifelse_02.sh
파일 관련 조건
연산자 결과
| 연산자 | 결과 |
| -d 파일 이름 | 주어진 파일 이름이 디렉터리이면 참 |
| -e 파일 이름 | 주어진 파일 이름이 존재하면 참 |
| -f 파일 이름 | 주어진 파일 이름이 일반 파일이면 참 |
| -g 파일 이름 | 주어진 파일 이름이 set-group-id가 설정되면 참 |
| -r 파일 이름 | 주어진 파일 이름이 읽기가 가능하면 참 |
| -s 파일 이름 | 주어진 파일의 크기가 0이 아니면 참 |
| -u 파일 이름 | 주어진 파일 이름이 set-user-id가 설정되면 참 |
| -w 파일 이름 | 주어진 파일 이름이 쓰기 가능한 상태이면 참 |
| -x 파일 이름 | 주어진 파일 이름이 실행 가능한 상태이면 참 |
cf. setuid를 하면 파일 권한에서 -rws와 같이 원래 x가 써져있을 자리에 s가 들어감
예제
sudo gedit ifelse_03.sh
#! /bin/sh
sample=/lib/systemd/system/udev.service
if [ -f $sample ]
then
echo " >> result : True "
head -3 $sample
else
echo " >> result : False "
fi
exit 0
sh ifelse_03.sh
head -3 $sample : 앞에서부터 3줄 출력
case~esac 문
if~else문은 조건이 많아지게 되면 구문이 복잡해지는 단점 존재
if~else문은 조건을 참과 거짓으로 판별하여 참과 거짓에 해당하는 명령을 수행
case~esac문은 여러 개의 조건을 펼쳐놓고 어느 조건에 해당되는지를 판별하여 명령을 수행하는 방식으로 구문 전개
- case~esac 문법구조
case 파라미터 또는 키보드 입력값 in
조건1)
명령1;;
조건2)
명령2;;
조건n)
명령n;;
*)
앞에서 주어진 조건 이외의 모든 경우 실행할 명령;;
esac
cf. 명령 끝에 ;; 를 붙이는 이유: case문 탈출하기 위함
예제
sudo gedit case_01.sh
#! /bin/sh
echo " >> season choice : Spring / Summer / Fall / Winter "
case "$1" in
Spring)
echo " >> choice : Spring ";;
Summer)
echo " >> choice : Summer ";;
Fall)
echo " >> choice : Fall ";;
Winter)
echo " >> choice : Winter ";;
*)
echo " No choice ~ ";;
sh case_01.sh Spring
sh case_01.sh exit
키보드로 Yes 또는 No를 입력하거나 Y 또는 y 그리고 알파벳 n 또는 N으로 시작하는 모든 단어가 입력될 경우 해당 조건을 수행하도록 *를 함께 사용하여 조건을 선언하는 프로그램
예제
sudo gedit case_02.sh
#! /bin/sh
echo " >> state choice : (Yes / No / Y / N) "
read mind
case $mind in
Yes | YES | yes | Y | y)
echo " >> choice : Yes "
echo " >> result : Linux Master ";;
[nN]*)
echo " >> choice : No "
echo " >> result : Good Luck~ ";;
*)
echo " >> choice error !! ";;
esac
exit 0
sh case_02.sh
[nN]* : n또는 N으로 시작 (n, N만있어도 됨)
;; 이 없을 경우 case문을 빠져나오지 않고 그 다음 줄로 커서를 이동시킴
Yes | YES | yes | Y | y) : 5개 중 하나에 해당하면 됨(or 연산)
조건문에서의 관계 연산자
- and 연산
if [ 조건1 ] && [ 조건2 ]
if [ 조건1 -a 조건2 ]
- or 연산
if [ 조건1 ] || [ 조건2 ]
if [ 조건1 -o 조건2 ]
예제
sudo gedit ifandor.sh
#! /bin/sh
echo ">> Search Name : "
read file_name
if [ -f $file_name ] && [ -s $file_name ]; then
echo ">> File Select : $file_name "
head -3 $file_name
else
echo ">> Search File : $file_name "
echo ">> File not found "
fi
exit 0
sh ifandor.sh
echo “>> Search Name : “ 과 read file_name을 한 줄로 병합하면,
read -p “Search Name : “ file_name 이라고 함
(ppt에는 없는 문제) - 일반 파일 혹은 디렉터리일 때 파일 이름 출력 (-o 옵션 이용)
#! /bin/sh
read -p "Search name: " file_name
if [ -f $file_name -o -d $file_name ]; then
echo ">> File Select : $file_name "
else
echo ">> Search File : $file_name "
echo ">> File not found "
fi
exit 0
문제 12-03
- 셸 스크립트 프로그램 test_1303.sh 작성하기
- 명령 수행 파라미터 $1 사용하기
- 혈액형을 알파벳 대/소문자 구별 없이 A, B, O, AB 조건으로 정하기
- 혈액형 이외의 알파벳에 대해서는 다시 입력하기
- 혈액형에 대해서는 출력 메시지는 “무슨 형을 선택하였습니다.”로 출력하기
- 마지막에는 “프로그램을 종료합니다.”를 출력하기
$ gedit test_1303.sh
#! /bin/sh
echo ">> 명령 수행 파라미터 (A, B, O, AB)"
case "$1" in
A | a)
echo "A형을 선택하였습니다." ;;
B | b)
echo "B형을 선택하였습니다." ;;
O | o)
echo "O형을 선택하였습니다." ;;
AB | ab)
echo "AB형을 선택하였습니다." ;;
*)
echo "혈액형은 알파벳 대/소문자 구별 없이 A, B, O, AB만 가능합니다." ;;
esac
echo "프로그램을 종료합니다."
exit 0
$ sh test_1303.sh
'공부 기록 > 리눅스 기초' 카테고리의 다른 글
| [리눅스 기초] 11 소프트웨어 관리 (1) | 2026.01.17 |
|---|---|
| [리눅스 기초] 10 프로세스 관리 (0) | 2026.01.17 |
| [리눅스 기초] 09 프로세스 관리 (0) | 2025.11.03 |
| [리눅스 기초] 08 관리자 권한 실행 (0) | 2025.11.03 |
| [리눅스 기초] 07 파일 접근 권한 설정 (0) | 2025.11.02 |