Home Shell Scripting
Post
Cancel

Shell Scripting

쉘 스크립팅 (Shell Scripting)

개요

쉘 스크립트는 쉘 명령어를 파일에 저장해서 자동으로 실행하는 방식이다. 배포, 백업, 모니터링 등 반복되는 작업을 자동화할 때 가장 많이 사용된다.

1
2
3
4
5
6
7
8
9
10
# 수동으로 매번 입력하는 방식
mkdir -p /backup
cp -r /home/ubuntu/app /backup/app-$(date +%Y%m%d)
tar -czf /backup/backup.tar.gz /backup/app

# 스크립트로 자동화 (backup.sh)
#!/bin/bash
mkdir -p /backup
cp -r /home/ubuntu/app /backup/app-$(date +%Y%m%d)
tar -czf /backup/backup.tar.gz /backup/app

쉘 스크립트 작성 기초

파일 생성 및 권한

1
2
3
4
5
6
7
8
9
10
11
# 1. 스크립트 파일 생성
cat > backup.sh << 'EOF'
#!/bin/bash
echo "백업 시작..."
EOF

# 2. 실행 권한 추가
chmod +x backup.sh

# 3. 실행
./backup.sh

Shebang (#!)

1
#!/bin/bash

파일의 첫 줄인 shebang은 “이 파일을 어떤 인터프리터로 실행할지”를 지정한다.

1
2
3
#!/bin/bash       # Bash로 실행
#!/bin/sh         # 표준 sh로 실행
#!/usr/bin/python # Python으로 실행

변수 (Variables)

변수 선언 및 사용

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash

# 변수 선언 (공백 없음!)
NAME="John"
AGE=30
PATH_TO_APP="/home/ubuntu/app"

# 변수 사용 ($로 참조)
echo "이름: $NAME"
echo "나이: $AGE"
echo "경로: $PATH_TO_APP"

주의: 공백이 있으면 오류 발생

1
2
3
4
5
# 잘못된 방법
NAME = "John"  # 오류!

# 올바른 방법
NAME="John"    # OK

명령어 결과를 변수에 저장

1
2
3
4
5
6
7
8
#!/bin/bash

# 방법 1: $(...)
CURRENT_DATE=$(date +%Y%m%d)
echo "오늘 날짜: $CURRENT_DATE"

# 방법 2: `...` (이전 방식, 가독성 낮음)
CURRENT_DATE=`date +%Y%m%d`

조건문 (if / else)

기본 구조

1
2
3
4
5
6
7
8
9
#!/bin/bash

AGE=25

if [ $AGE -ge 18 ]; then
    echo "성인입니다"
else
    echo "미성년자입니다"
fi

비교 연산자

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 숫자 비교
[ $A -eq $B ]   # 같음 (equal)
[ $A -ne $B ]   # 다름 (not equal)
[ $A -lt $B ]   # 작음 (less than)
[ $A -le $B ]   # 작거나 같음
[ $A -gt $B ]   # 큼 (greater than)
[ $A -ge $B ]   # 크거나 같음

# 문자열 비교
[ "$A" = "$B" ]   # 같음
[ "$A" != "$B" ]  # 다름
[ -z "$A" ]       # 빈 문자열인가?
[ -n "$A" ]       # 비어있지 않은가?

# 파일 확인
[ -f $FILE ]      # 파일이 존재하는가?
[ -d $DIR ]       # 디렉토리가 존재하는가?
[ -e $PATH ]      # 경로가 존재하는가?
[ -r $FILE ]      # 읽기 권한이 있는가?
[ -w $FILE ]      # 쓰기 권한이 있는가?
[ -x $FILE ]      # 실행 권한이 있는가?

실제 예시

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash

FILE="/home/ubuntu/app/config.sh"

if [ -f $FILE ]; then
    echo "파일이 존재합니다"
    source $FILE  # 파일 실행
else
    echo "파일이 없습니다"
    exit 1        # 오류로 종료
fi

if / elif / else

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash

HOUR=$(date +%H)

if [ $HOUR -lt 12 ]; then
    echo "좋은 아침입니다"
elif [ $HOUR -lt 18 ]; then
    echo "좋은 오후입니다"
else
    echo "좋은 밤입니다"
fi

반복문 (Loop)

for 루프

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

# 1. 범위 지정
for i in 1 2 3 4 5; do
    echo "번호: $i"
done

# 2. 시퀀스 생성
for i in {1..5}; do
    echo "번호: $i"
done

# 3. 배열 순회
FILES=("file1.txt" "file2.txt" "file3.txt")
for FILE in "${FILES[@]}"; do
    echo "처리 중: $FILE"
done

# 4. 명령어 결과 순회
for FILE in $(ls *.txt); do
    echo "파일: $FILE"
done

while 루프

1
2
3
4
5
6
7
#!/bin/bash

COUNT=1
while [ $COUNT -le 5 ]; do
    echo "카운트: $COUNT"
    COUNT=$((COUNT + 1))  # 수식 계산
done

반복 제어

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash

for i in {1..10}; do
    if [ $i -eq 5 ]; then
        continue  # 다음 반복으로 (5는 건너뜀)
    fi
    
    if [ $i -eq 8 ]; then
        break     # 루프 탈출
    fi
    
    echo "번호: $i"
done

함수 (Functions)

함수 정의 및 호출

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

# 함수 정의
backup_files() {
    echo "백업 중..."
    cp -r /home/ubuntu/app /backup/
    echo "백업 완료"
}

# 함수 호출
backup_files
backup_files

매개변수와 반환값

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

# 매개변수 받기
greet() {
    local NAME=$1      # 첫 번째 매개변수
    local AGE=$2       # 두 번째 매개변수
    
    echo "안녕하세요, $NAME님! 나이: $AGE"
    
    return 0  # 반환값 (0 = 성공, 1 = 실패)
}

# 함수 호출
greet "John" 30
greet "Jane" 25

함수의 반환값 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

copy_file() {
    if cp $1 $2; then
        return 0  # 성공
    else
        return 1  # 실패
    fi
}

if copy_file "source.txt" "dest.txt"; then
    echo "복사 성공"
else
    echo "복사 실패"
fi

실제 예시: 배포 스크립트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/bin/bash

# 에러 발생 시 즉시 종료
set -e

# 변수 선언
APP_DIR="/home/ubuntu/app"
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)

# 함수: 백업
backup() {
    echo "백업 중... ($DATE)"
    cp -r $APP_DIR $BACKUP_DIR/app-$DATE
    echo "백업 완료"
}

# 함수: 배포
deploy() {
    echo "배포 중..."
    cd $APP_DIR
    git pull origin main
    npm install
    npm run build
    systemctl restart app
    echo "배포 완료"
}

# 함수: 검증
validate() {
    if curl -f http://localhost:3000 > /dev/null; then
        echo "서비스 정상 작동"
        return 0
    else
        echo "서비스 오류"
        return 1
    fi
}

# 메인 로직
echo "배포 시작: $DATE"
backup
deploy

if validate; then
    echo "배포 성공"
else
    echo "검증 실패, 이전 버전으로 복구"
    cp -r $BACKUP_DIR/app-$DATE $APP_DIR
    systemctl restart app
    exit 1
fi

특수 변수

1
2
3
4
5
6
7
8
9
#!/bin/bash

echo $0      # 스크립트 이름
echo $1      # 첫 번째 인자
echo $2      # 두 번째 인자
echo $@      # 모든 인자 (배열)
echo $#      # 인자 개수
echo $?      # 이전 명령어의 반환값 (0 = 성공)
echo $$      # 현재 프로세스 ID

실제 사용

1
2
3
4
5
6
7
8
9
10
#!/bin/bash

# 스크립트 실행: ./script.sh apple banana cherry

echo "스크립트: $0"
echo "첫 번째: $1"  # apple
echo "두 번째: $2"  # banana
echo "세 번째: $3"  # cherry
echo "모두: $@"     # apple banana cherry
echo "개수: $#"     # 3

주의사항

set -e (에러 발생 시 즉시 종료)

1
2
3
4
5
#!/bin/bash
set -e

cd /nonexistent  # 오류 발생
echo "이 줄은 실행되지 않음"

set -x (디버그 모드)

1
2
3
4
5
#!/bin/bash
set -x  # 실행할 명령어 출력

mkdir -p /backup
cp -r /app /backup/
1
2
+ mkdir -p /backup
+ cp -r /app /backup/

참고

  • 스크립트는 간단한 작업 자동화부터 복잡한 배포 파이프라인까지 다양하게 사용된다.
  • 복잡한 로직은 Python이나 Go 같은 언어가 더 적합할 수 있다.
  • 본 노트의 예시는 #!/bin/bash 기준이다.
This post is licensed under CC BY 4.0 by the author.