10-3. Shell Scripting

1. 쉘 스크립팅의 이해

쉘 스크립팅은 운영체제 쉘(Shell)의 명령어를 조합하여 실행되는 일련의 명령 집합을 의미합니다. 마치 요리 레시피처럼, 쉘 스크립트는 쉘에게 수행해야 할 일련의 작업들을 순서대로 지시합니다. 이러한 스크립트는 반복적인 작업을 자동화하고, 시스템 관리 작업을 효율적으로 처리하며, 복잡한 프로세스를 단순화하는 데 매우 유용합니다. 리눅스 환경에서 쉘 스크립트는 시스템 관리, 배치 작업, 소프트웨어 설치, 설정, 데이터 처리 등 다양한 분야에서 핵심적인 역할을 수행합니다.

1) 쉘 스크립팅의 필요성

쉘 스크립팅은 단순한 명령어 실행 이상의 가치를 지닙니다.

  • 자동화: 반복적인 작업을 자동화하여 시간과 노력을 절약합니다. 예를 들어, 매일 특정 시간대에 로그 파일을 백업하는 스크립트를 작성할 수 있습니다.
  • 유지보수 용이성: 복잡한 시스템 관리 작업을 스크립트로 캡슐화하여 유지보수를 용이하게 합니다.
  • 재사용성: 작성된 스크립트는 필요에 따라 여러 번 재사용할 수 있습니다.
  • 확장성: 쉘 스크립트는 다른 프로그램이나 스크립트와 쉽게 통합될 수 있습니다.

2) 쉘의 종류

리눅스 시스템에는 다양한 쉘이 존재하며, 각 쉘은 고유한 특징과 기능을 제공합니다.

  • Bash (Bourne Again Shell): 가장 널리 사용되는 쉘로, Bourne 쉘의 확장 버전입니다. Bash는 강력한 기능, 유연성, 광범위한 호환성을 제공합니다.
  • Zsh (Z Shell): Bash보다 더 많은 기능과 커스터마이징 옵션을 제공하며, 사용자 친화적인 환경을 제공합니다.
  • Ksh (Korn Shell): Bash와 유사한 기능을 제공하며, 상업용 시스템에서 널리 사용됩니다.
  • Sh (Bourne Shell): 가장 기본적인 쉘로, 다른 쉘의 기반이 되었습니다.

본 문서에서는 Bash를 기준으로 설명합니다.

2. 쉘 스크립트 작성 기본

쉘 스크립트 작성은 텍스트 파일을 만들고, 쉘 명령어를 입력하는 것으로 시작합니다.

1) 스크립트 파일 생성 및 실행

  • 쉘 스크립트는 일반적으로 .sh 확장자를 갖는 텍스트 파일로 저장됩니다.

    bash touch my_script.sh

  • 스크립트를 실행하기 전에 실행 권한을 부여해야 합니다.

    bash chmod +x my_script.sh

  • 스크립트를 실행하는 방법은 다음과 같습니다.

    bash ./my_script.sh

2) 쉘 스크립트의 구조

쉘 스크립트는 일반적으로 다음과 같은 구조를 가집니다.

#!/bin/bash
# 주석: 스크립트에 대한 설명

# 변수 선언 및 초기화
name="John Doe"

# 명령어 실행
echo "Hello, $name!"
  • Shebang (#!): 스크립트의 첫 번째 줄에 위치하며, 스크립트를 실행할 인터프리터를 지정합니다. (#!/bin/bash)
  • 주석: # 문자로 시작하며, 스크립트의 설명을 제공합니다.
  • 변수: 데이터를 저장하는 데 사용됩니다.
  • 명령어: 쉘에서 실행할 명령어입니다.

3) 변수와 데이터 타입

쉘 스크립트에서 변수는 데이터를 저장하는 데 사용됩니다. 변수를 선언할 때 var_name=value 형식으로 값을 할당합니다.

  • 변수 선언: variable_name="value"
  • 변수 사용: $variable_name` 또는 `${variable_name}

쉘 스크립트는 명시적인 데이터 타입 선언을 지원하지 않지만, 문자열, 숫자, 배열 등의 데이터를 처리할 수 있습니다.

  • 문자열: name="John Doe"
  • 숫자: age=30
  • 배열: fruits=("apple" "banana" "orange")

4) 명령어 실행 및 리다이렉션

쉘 스크립트에서는 쉘 명령어를 직접 실행할 수 있습니다. 명령어의 실행 결과는 표준 출력(stdout)으로 표시됩니다.

  • echo 명령어: 텍스트를 출력합니다.
  • 리다이렉션(>): 명령의 출력을 파일로 저장합니다.
  • 파이프(|): 한 명령의 출력을 다른 명령의 입력으로 사용합니다.
echo "Hello, world!" > output.txt  # "Hello, world!"를 output.txt에 저장
ls -l | grep "txt"                 # ls -l의 결과를 txt를 포함하는 행만 필터링

3. 제어 구조 및 연산

쉘 스크립트는 제어 구조와 연산을 통해 복잡한 로직을 구현할 수 있습니다.

1) 조건문

if, elif, else 구문을 사용하여 조건을 평가하고, 조건에 따라 다른 코드를 실행합니다.

if [ "$age" -gt 18 ]; then
  echo "You are an adult."
elif [ "$age" -eq 18 ]; then
  echo "You are an adult, congrats!"
else
  echo "You are a minor."
fi
  • [ ] 내의 조건은 참/거짓을 평가하며, = (같음), -eq(같음), -ne(같지 않음), -gt(보다 큼), -lt(보다 작음), -ge(크거나 같음), -le(작거나 같음) 등의 연산자를 사용할 수 있습니다.
  • 문자열 비교에는 <mark class="highlight"><strong><u> (같음), !</u></strong></mark>(같지 않음) 연산자를 사용합니다.
  • 논리 연산자 (&&, ||, !)를 사용하여 복잡한 조건을 구성할 수 있습니다.

2) 반복문

for, while, until 구문을 사용하여 코드를 반복적으로 실행합니다.

# for 루프
for fruit in "apple" "banana" "orange"; do
  echo "I like $fruit"
done

# while 루프
count=1
while [ "$count" -le 5 ]; do
  echo "Count: $count"
  count=$((count + 1))  # 변수 값을 증가시킬 때 $((...)) 사용
done

# until 루프
count=1
until [ "$count" -gt 5 ]; do
  echo "Count: $count"
  count=$((count + 1))
done

3) 연산자

쉘 스크립트는 산술 연산, 문자열 연산, 논리 연산 등 다양한 연산을 지원합니다.

  • 산술 연산: +, -, *, /, % ($((...)) 또는 expr 명령어를 사용)
  • 문자열 연산: length, substring, concatenation
  • 논리 연산: && (AND), || (OR), ! (NOT)

4. 함수와 스크립트 관리

함수를 사용하면 코드를 모듈화하고 재사용성을 높일 수 있으며, 스크립트 관리를 효율적으로 수행할 수 있습니다.

1) 함수 정의 및 호출

함수를 정의하고 호출하여 코드를 구조화할 수 있습니다.

# 함수 정의
hello() {
  echo "Hello, $1!"  # $1은 첫 번째 인수를 나타냄
}

# 함수 호출
hello "World"
  • 함수는 function 함수이름 () { ... } 형식으로 정의됩니다.
  • 함수 내에서 $`를 사용하여 인수에 접근합니다. (`$1, $2, ...).
  • 함수의 반환 값은 return 문을 사용하여 지정할 수 있습니다. (0은 성공, 0이 아닌 값은 실패)

2) 스크립트 인자

스크립트 실행 시 인자를 전달받아 사용할 수 있습니다.

#!/bin/bash

# 스크립트 실행: ./my_script.sh arg1 arg2
echo "첫 번째 인자: $1"
echo "두 번째 인자: $2"
echo "모든 인자: $*"
echo "인자의 개수: $#"
  • $1`, `$2, ...는 스크립트 인자를 나타냅니다.
  • $*는 모든 인자를 나타냅니다.
  • $#는 인자의 개수를 나타냅니다.

3) 스크립트 종료

쉘 스크립트는 exit 명령어를 사용하여 종료할 수 있습니다. exit 명령어에 인수를 전달하여 종료 상태를 지정할 수 있습니다. (0은 성공, 0이 아닌 값은 실패)

exit 0  # 정상 종료
exit 1  # 오류로 인해 종료

5. 실용적인 쉘 스크립트 예제

다음은 쉘 스크립팅의 기본적인 개념을 활용한 실용적인 예제입니다.

1) 파일 백업 스크립트

이 스크립트는 지정된 디렉터리의 파일을 압축하여 백업합니다.

#!/bin/bash
# 백업 스크립트

# 대상 디렉터리
SOURCE_DIR="/home/user/documents"

# 백업 파일 이름
BACKUP_FILE="backup_$(date +%Y%m%d_%H%M%S).tar.gz"

# 백업 파일 저장 위치
BACKUP_DIR="/home/user/backups"

# 백업 디렉터리가 없으면 생성
if [ ! -d "$BACKUP_DIR" ]; then
  mkdir -p "$BACKUP_DIR"
fi

# 압축 및 백업
tar -czvf "$BACKUP_DIR/$BACKUP_FILE" "$SOURCE_DIR"

# 백업 성공 여부 확인
if [ $? -eq 0 ]; then
  echo "백업 완료: $BACKUP_DIR/$BACKUP_FILE"
else
  echo "백업 실패"
fi

2) 로그 파일 분석 스크립트

이 스크립트는 로그 파일에서 특정 오류 메시지를 검색하고, 해당 메시지의 발생 횟수를 계산합니다.

#!/bin/bash
# 로그 파일 분석 스크립트

# 로그 파일 경로
LOG_FILE="/var/log/syslog"

# 검색할 오류 메시지
ERROR_MESSAGE="error"

# 오류 메시지 발생 횟수 계산
ERROR_COUNT=$(grep "$ERROR_MESSAGE" "$LOG_FILE" | wc -l)

# 결과 출력
echo "오류 메시지 '$ERROR_MESSAGE' 발생 횟수: $ERROR_COUNT"

6. 쉘 스크립팅 팁 및 주의사항

쉘 스크립팅을 효과적으로 사용하기 위한 팁과 주의사항을 소개합니다.

1) 디버깅

  • set -x 명령어를 사용하여 스크립트 실행 시 각 명령어를 출력하여 디버깅합니다.
  • set -e 명령어를 사용하여 오류 발생 시 스크립트 실행을 중단합니다.
  • echo 명령어를 사용하여 변수 값과 중간 결과를 확인합니다.

2) 보안

  • 사용자 입력을 신뢰하지 말고, 입력 값을 검증합니다.
  • 파일 권한을 적절하게 설정합니다.
  • 민감한 정보를 스크립트에 하드코딩하지 않습니다.

3) 코드 스타일

  • 가독성을 위해 스크립트에 주석을 추가합니다.
  • 들여쓰기를 사용하여 코드를 구조화합니다.
  • 변수와 함수에 의미 있는 이름을 사용합니다.
  • 일관된 코드 스타일을 유지합니다.

4) 기타

  • 쉘 스크립트에서 사용 가능한 유틸리티 명령어를 숙지합니다. (예: grep, sed, awk, find, sort)
  • 다양한 쉘 스크립팅 예제를 참고하여 학습합니다.
  • 온라인 쉘 스크립팅 도구 (예: shellcheck)를 사용하여 코드를 검사합니다.

7. 결론

쉘 스크립팅은 리눅스 시스템 관리 및 자동화에 필수적인 기술입니다. 쉘 스크립트의 기본 개념, 제어 구조, 함수, 스크립트 관리 방법을 익히고, 실용적인 예제를 통해 쉘 스크립팅 능력을 향상시킬 수 있습니다. 쉘 스크립트는 단순한 작업의 자동화부터 복잡한 시스템 관리 작업까지, 다양한 분야에서 활용될 수 있으며, 숙련된 쉘 스크립터는 시스템 효율성을 극대화하고, 작업 생산성을 향상시킬 수 있습니다. 꾸준한 연습과 학습을 통해 쉘 스크립팅 전문가가 될 수 있습니다.

비슷한 글 추천

Comments (0)

No comments yet. Be the first to comment!