셸 스크립팅 기본 가이드

1. 셸(Shell) 개요

셸은 명령어 해석기로, 사용자가 리눅스 커널에 요청을 보내 프로그램을 실행할 수 있는 인터페이스 역할을 시스템 수준에서 수행합니다. 사용자는 셸을 통해 프로세스를 시작하고, 일시 중지하며, 중지시키고 심지어 일부 프로그램을 작성할 수 있습니다.

리눅스에서 제공하는 셸 해석기 목록:

[사용자@호스트 ~]$ cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh

bash와 sh의 관계

[사용자@호스트 bin]$ ll | grep bash
-rwxr-xr-x. 1 root root 941880 5월  11 2016 bash
lrwxrwxrwx. 1 root root      4 5월  27 2017 sh -> bash

CentOS의 기본 해석기는 bash입니다

[사용자@호스트 bin]$ echo $SHELL
/bin/bash

2. 셸 스크립트 입문

2.1 스크립트 형식

#!/bin/bash  # 이렇게 시작 (해석기 지정)

2.2 첫 번째 셸 스크립트: 안녕하세요

【예시】:

[사용자@호스트 데이터]$ touch hello.sh
[사용자@호스트 데이터]$ vi hello.sh

hello.sh에 다음 내용 입력
#!/bin/bash
echo "안녕하세요"

스크립트의 일반적인 실행 방법

방법 1: bash/sh + 상대/절대 경로 (스크립트에 +x 권한 부여 불필요)

방법 2: 스크립트 직접 실행 (실행 권한 필요)

주의:

  • 방법 1: 본질적으로 bash 해석기가 스크립트를 실행해주므로, 스크립트 자체에 실행 권한이 필요 없습니다.
  • 방법 2: 본질적으로 스크립트가 직접 실행되므로, 실행 권한이 필요합니다.

3. 변수

3.1 시스템 미리 정의된 변수

일반적인 시스템 변수

$HOME, $PWD, $SHELL, $USER, $PATH 등

【예시】

시스템 변수 값 확인: echo $HOME

현재 셸의 모든 변수 표시: set

3.2 사용자 정의 변수

기본 구문

  • 변수 정의: 변수=값
  • 변수 제거: unset 변수
  • 정적 변수 선언: readonly 변수 (참고: unset 불가)

변수 정의 규칙

  • 변수 이름은 Java와 동일한 규칙을 따릅니다.
  • "=" 양쪽에 공백이 없어야 합니다.
  • 기본적으로 문자열 타입입니다.
  • 변수 값에 공백이 있을 경우, 큰따옴표나 작은따옴표를 사용합니다.

【예시】

(1) 변수 A 정의

[사용자@호스트 데이터]$ A=5
[사용자@호스트 데이터]$ echo $A
5

(2) 변수 A에 재할당

[사용자@호스트 데이터]$ A=8
[사용자@호스트 데이터]$ echo $A
8

(3) 변수 A 제거

[사용자@호스트 데이터]$ unset A
[사용자@호스트 데이터]$ echo $A

(4) 정적 변수 B=2 선언 (unset 불가)

[사용자@호스트 데이터]$ readonly B=2
[사용자@호스트 데이터]$ echo $B
2
[사용자@호스트 데이터]$ B=9
-bash: B: readonly variable

(5) bash에서 변수는 기본적으로 문자열 타입이며, 직접 숫자 연산을 수행할 수 없음

[사용자@호스트102 ~]$ C=1+2
[사용자@호스트102 ~]$ echo $C
1+2

(6) 변수 값에 공백이 있는 경우, 큰따옴표나 작은따옴표로 감싸야 함

[사용자@호스트102 ~]$ D=I love banzhang
-bash: world: command not found
[사용자@호스트102 ~]$ D="I love banzhang"
[사용자@호스트102 ~]$ echo $D
I love banzhang

3.3 특수 변수

3.3.1 $n

기본 구문: $n

기능: n은 숫자입니다.

  • $0: 스크립트 이름
  • $1-$9: 첫 번째부터 아홉 번째까지의 매개변수
  • n>10일 경우 중괄호 사용 필요 (예: ${10})

【예시】

[관리자@1025 데이터]# vim args.sh

#!/bin/bash
echo "$0  $1   $2"

[관리자@1025 데이터]# bash args.sh 1 2 3
args.sh 1 2

3.3.2 $#

기본 구문: $#

기능: 모든 입력 매개변수의 개수를 가져옵니다. 주로 루프에 사용됩니다.

【예시】

[관리자@1025 데이터]# vim args.sh

#!/bin/bash
echo "$0  $1   $2"
echo $#

[관리자@1025 데이터]# bash args.sh 1 2 3
args.sh 1 2
3

3.3.3 $*, $@

기본 구문

  • $*: 모든 매개변수를 하나의 문자열로 취급
  • $@: 모든 매개변수를 각각 개별적으로 취급

【예시】

[관리자@1025 데이터]# vim args.sh

#!/bin/bash
echo "$0  $1   $2"
echo $#
echo $*
echo $@

[관리자@1025 데이터]# bash args.sh 1 2 3
args.sh 1 2
3
1 2 3
1 2 3

3.3.4 $?

기본 구문: $?

기능: 마지막으로 실행된 명령어의 반환 상태입니다. 이전 명령어가 성공적으로 실행되면 0을 반환하고, 오류가 발생하면 0이 아닌 값을 반환합니다.

【예시】 greeting.sh 스크립트가 올바르게 실행되는지 확인

[관리자@1025 데이터]# bash greeting.sh 
안녕하세요!
[관리자@1025 데이터]# echo $?
0

4. 연산자

기본 구문

" $[연산식] "

【예시】 (2+3)*4 값 계산

[관리자@1025 데이터]# sum=$(((2+3)*4))
[관리자@1025 데이터]# echo sum
sum
[관리자@1025 데이터]# echo $sum
20
[관리자@1025 데이터]# sum=$[(2+3)*4]
[관리자@1025 데이터]# echo $sum
20

5. 조건문

기본 구문

  • (1) test condition
  • (2) [ condition ] (주의: condition 앞뒤에 공백이 있어야 함)

주의: 조건이 비어있지 않으면 true로 간주됩니다. [ 문자열 ]은 true를 반환하지만, []는 false를 반환합니다.

일반적인 조건 판별

● 두 정수 비교

연산자의미
-lt보다 작음 (less than)
-gt보다 큼 (greater than)
-le보다 작거나 같음 (less equal)
-ge보다 크거나 같음 (greater equal)
-eq같음 (equal)
-ne같지 않음 (Not equal)
=문자열 비교

● 파일 권한 기준 판별

연산자의미
-r읽기 권한 (read)
-w쓰기 권한 (write)
-x실행 권한 (execute)

● 파일 타입 기준 판별

연산자의미
-f파일이 존재하고 일반 파일인 경우 (file)
-e파일이 존재하는 경우 (existence)
-d존재하고 디렉토리인 경우 (directory)

【예시】

(1) 23이 22보다 크거나 같은지 확인

[관리자@1025 데이터]# [ 23 -ge 22 ]
[관리자@1025 데이터]# echo $?
0

(2) greeting.sh에 쓰기 권한이 있는지 확인

[관리자@1025 데이터]# ll
총량 8
-rw-r--r--. 1 root root 32 12월  8 07:32 greeting.sh
-rw-r--r--. 1 root root 52 12월  8 07:27 args.sh
[관리자@1025 데이터]# [ -w greeting.sh ]
[관리자@1025 데이터]# echo $?
0

(3) /opt/datas 디렉토리에 파일이 존재하는지 확인

[관리자@1025 opt]# [ -e /opt/datas ]
[관리자@1025 opt]# echo $?
0

(4) 다중 조건 판별 (&&는 이전 명령어가 성공했을 때 다음 명령어를 실행하고, ||는 이전 명령어가 실패했을 때 다음 명령어를 실행합니다)

[관리자@1025 데이터]# [ condition ] && echo true || echo false

6. 제어 흐름 (중요)

6.1 if 문

기본 구문

if [ 조건식 ]; then
    프로그램
fi
또는
if [ 조건식 ]
    then
        프로그램
    elif [ 조건식 ]
        then
            프로그램
    else
        프로그램
    fi

주의:

  • [ 조건식 ]에서 대괄호와 조건식 사이에 공백이 있어야 합니다.
  • if 뒤에 공백이 있어야 합니다.

【예시】

숫자 하나를 입력받아, 1이면 "첫 번째 선택"을 출력하고, 2이면 "두 번째 선택"을 출력하며, 3이면 "세 번째 선택"을 출력하고, 그 외에는 아무것도 출력하지 않습니다.

[관리자@1025 데이터]# vim check.sh 
[관리자@1025 데이터]# bash check.sh 3
세 번째 선택
[관리자@1025 데이터]# bash check.sh 1
첫 번째 선택
[관리자@1025 데이터]# bash check.sh 2
두 번째 선택

#!/bin/bash
if [ $1 -eq "1" ]
then
        echo "첫 번째 선택"
elif [ $1 -eq "2" ]
then
        echo "두 번째 선택"
elif [ $1 -eq "3" ]
then
        echo "세 번째 선택"
fi

6.2 case 문

기본 구문

case $변수명 in
    "값1")
        변수값이 값1과 같으면 프로그램1 실행
        ;;
    "값2")
        변수값이 값2와 같으면 프로그램2 실행
        ;;
    … 다른 분생들 …
    *)
        변수값이 위의 값들과 다르면 이 프로그램 실행
        ;;
esac

주의사항:

  • case 행 끝에는 반드시 단어 "in"이 있어야 하고, 각 패턴 일치는 오른쪽 괄호 ")"로 끝나야 합니다.
  • 이중 세미콜론 ";;"은 명령어 시퀀스의 끝을 의미하며, Java의 break와 같습니다.
  • 마지막의 "* )"는 기본 패턴을 의미하며, Java의 default와 같습니다.

【예시】

숫자 하나를 입력받아, 1이면 "첫 번째 선택"을 출력하고, 2이면 "두 번째 선택"을 출력하며, 3이면 "세 번째 선택"을 출력하고, 그 외에는 "기본값 출력"을 출력합니다.

[관리자@1025 데이터]# vim case.sh
[관리자@1025 데이터]# bash case.sh 1
첫 번째 선택
[관리자@1025 데이터]# bash case.sh 2
두 번째 선택
[관리자@1025 데이터]# bash case.sh 3
세 번째 선택
[관리자@1025 데이터]# bash case.sh 7
기본값 출력

#!/bin/bash
case $1 in
"1")
        echo "첫 번째 선택"
;;
"2")
        echo "두 번째 선택"
;;
"3")
        echo "세 번째 선택"
;;
*)
        echo "기본값 출력"
;;
esac

6.3 for 반복문

기본 구문 1

for (( 초기값; 반복 조건; 변수 변경 ))
    do
        프로그램
    done

【예시】 1부터 100까지의 합 계산

[관리자@1025 데이터]# vim sum1.sh
[관리자@1025 데이터]# bash sum1.sh 
5050

#!/bin/bash
sum=0
for((i=0;i<=100;i++))
do
        sum=$[$sum+$i]
done
echo $sum

기본 구문 2

for 변수 in 값1 값2 값3…
    do
        프로그램
    done

【예시】

(1) 모든 입력 매개변수 출력

[관리자@1025 데이터]# print.sh
[관리자@1025 데이터]# bash print.sh kim lee park
kim님 안녕하세요
lee님 안녕하세요
park님 안녕하세요

#!/bin/bash
for i in $*
do
        echo "$i님 안녕하세요"
done

(2) $*와 $@의 비교

$*와 $@는 함수나 스크립트에 전달된 모든 매개변수를 나타냅니다.

【예시 1】 $*, $@에 ""를 사용하지 않을 경우, $1 $2 …$n 형식으로 모든 매개변수 출력

[관리자@1025 opt]# compare.sh
[관리자@1025 opt]# bash compare.sh kim lee park
kim님 안녕하세요
lee님 안녕하세요
park님 안녕하세요
---------------------
kim lee park님 안녕하세요

#!/bin/bash
for i in $*
do
      echo "$i님 안녕하세요"
done
echo "---------------------"
for j in $@
do      
        echo "$j님 안녕하세요"
done

【예시 2】 $*, $@에 ""를 사용할 경우, "$*"는 "$1 $2 …$n" 형식으로 전체 출력하고, "$@"는 "$1", "$2", …, "$n" 형식으로 분리하여 출력합니다.

[관리자@1025 opt]# compare.sh
[관리자@1025 opt]# bash compare.sh kim lee park
kim lee park님 안녕하세요
---------------------
kim님 안녕하세요
lee님 안녕하세요
park님 안녕하세요

#!/bin/bash 

for i in "$*" 
#$*의 모든 매개변수를 하나의 문자열로 취급하므로 이 for 루프는 한 번만 실행됩니다
        do 
                echo "$i님 안녕하세요"
        done 
echo "---------------------"
for j in "$@" 
#$@의 각 매개변수를 별개로 취급하므로 "$@"에 몇 개의 매개변수가 있으면 몇 번이나 루프가 실행됩니다
        do 
                echo "$j님 안녕하세요" 
done

6.4 while 반복문

기본 구문

while [ 조건식 ]
    do
        프로그램
    done

【예시】

[관리자@1025 데이터]# while_sum.sh
[관리자@1025 데이터]# bash while_sum.sh 
5050

#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
        s=$[$s+$i]
        i=$[$i+1]
done
echo $s

7. read로 콘솔 입력 읽기

기본 구문

read(옵션)(매개변수)
옵션:
-p: 값 읽기 시 지시어 지정
-t: 값 읽기 대기 시간(초) 지정
매개변수
변수: 값 읽기 위한 변수명 지정

【예시】 7초 내에 콘솔에서 이름 입력받기

[관리자@1025 데이터]# input.sh
[관리자@1025 데이터]# bash input.sh 
7초 안에 이름을 입력하세요: 홍길동
홍길동

#!/bin/bash
read -t 7 -p "7초 안에 이름을 입력하세요: " NAME
echo $NAME

8. 함수

8.1 시스템 함수

8.1.1 basename

기본 구문

basename [문자열/경로명] [접미사]

기능 설명: basename 명령어는 모든 접두사를 포함 마지막 '/' 문자까지 제거한 후 문자열을 표시합니다.

옵션:

접미사: 접미사가 지정된 경우, 경로명이나 문자열에서 접미사를 제거합니다.

【예시】 /opt/data.txt 경로의 파일명 추출

8.1.2 dirname

기본 구문

dirname 파일 절대 경로

기능 설명: 주어진 절대 경로 파일명에서 파일명(디렉토리가 아닌 부분)을 제거하고, 남은 경로(디렉토리 부분)를 반환합니다.

【예시】 data.txt 파일의 경로 가져오기

8.2 사용자 정의 함수

기본 구문

[ function ] 함수명[()]
{
    동작;
    [return 정수;]
}
함수명

주의:

  • 먼저 함수를 선언한 후 호출합니다.
  • 셸 스크립트는 한 줄씩 실행됩니다. 다른 언어처럼 먼저 컴파일하지 않습니다.
  • 함수 반환값은 $? 시스템 변수를 통해 얻을 수 있습니다. 명시적으로 return으로 반환할 수도 있고, 그렇지 않으면 마지막 명령어 실행 결과를 반환값으로 사용합니다. return 뒤에는 숫자 n(0-255)이 옵니다.

【예시】

[관리자@1025 opt]# calc.sh
[관리자@1025 opt]# bash calc.sh 
첫 번째 숫자를 입력하세요: 3
두 번째 숫자를 입력하세요: 5
8

function add()
{
    result=0
    result=$[ $1 + $2 ]
    echo "$result"
}

read -p "첫 번째 숫자를 입력하세요: " num1;
read -p "두 번째 숫자를 입력하세요: " num2;
add $num1 $num2;

태그: 셸 스크립팅 리눅스 명령어 bash 프로그래밍 시스템 자동화

6월 17일 20:04에 게시됨