쉘스크립트란?
쉘스크립트(Shell Script)는 Linux/Unix 셸에서 실행되는 명령어 모음 파일입니다. 확장자 .sh로 저장하며, 서버 관리, 배포 자동화, 크론잡 등 시스템 운영의 핵심 도구입니다. 대부분의 Linux 배포판에서 기본 셸인 Bash(Bourne Again Shell)를 기준으로 설명합니다.
이 글에서는 기본 문법, 변수, 조건문, 반복문, 함수, 그리고 실전 자동화 스크립트까지 다룹니다.
첫 번째 스크립트
쉘스크립트의 첫 줄은 셔뱅(Shebang) #!/bin/bash로 시작합니다. 이 줄이 운영체제에게 어떤 인터프리터로 실행할지 알려줍니다.
#!/bin/bash
# hello.sh — 첫 번째 쉘스크립트
echo "안녕하세요, 쉘스크립트입니다!"
echo "현재 사용자: $(whoami)"
echo "현재 경로: $(pwd)"
echo "오늘 날짜: $(date '+%Y-%m-%d %H:%M')"
스크립트를 실행하려면 실행 권한을 부여해야 합니다.
# 실행 권한 부여 후 실행
chmod +x hello.sh
./hello.sh
# 안녕하세요, 쉘스크립트입니다!
# 현재 사용자: ubuntu
# 현재 경로: /home/ubuntu
# 오늘 날짜: 2026-04-07 22:00
$(명령어) 구문은 명령어의 실행 결과를 문자열로 치환합니다. 백틱(`명령어`)과 동일한 기능이지만, 중첩이 가능한 $() 형태를 권장합니다.
변수
변수 선언 시 = 양쪽에 공백이 없어야 합니다. 참조할 때는 $변수 또는 ${변수}를 사용합니다.
#!/bin/bash
# 변수 선언 (= 양쪽 공백 금지!)
PROJECT="my-app"
VERSION="2.1.0"
BUILD_DIR="/opt/${PROJECT}/build"
echo "프로젝트: ${PROJECT} v${VERSION}"
echo "빌드 경로: ${BUILD_DIR}"
# 읽기 전용 변수
readonly MAX_RETRY=3
# 환경변수 내보내기 (자식 프로세스에 전달)
export API_KEY="your-secret-key"
# 사용자 입력
read -p "배포할 환경을 선택하세요 (dev/prod): " ENV
echo "선택된 환경: ${ENV}"
| 구문 | 설명 | 예시 |
|---|---|---|
$VAR | 변수 참조 | echo $HOME |
${VAR} | 명시적 참조 (권장) | echo ${HOME}/bin |
${VAR:-기본값} | 변수 미설정 시 기본값 | ${PORT:-8080} |
${VAR:?에러메시지} | 변수 미설정 시 에러 | ${DB_HOST:?필수값} |
${#VAR} | 문자열 길이 | ${#PROJECT} → 6 |
$1, $2 | 위치 매개변수 | ./script.sh arg1 arg2 |
$@ | 모든 인수 (개별) | for arg in "$@" |
$# | 인수 개수 | if [ $# -eq 0 ] |
$? | 직전 명령 종료 코드 | 0=성공, 1+=실패 |
조건문
Bash의 조건문은 if [ 조건 ] 또는 if [[ 조건 ]] 형태입니다. [[ ]]는 Bash 확장 구문으로, 패턴 매칭과 정규표현식을 지원합니다.
#!/bin/bash
# 조건문 예제
# 숫자 비교
COUNT=15
if [ "${COUNT}" -gt 10 ]; then
echo "${COUNT}는 10보다 큽니다"
elif [ "${COUNT}" -eq 10 ]; then
echo "${COUNT}는 10과 같습니다"
else
echo "${COUNT}는 10보다 작습니다"
fi
# 문자열 비교
ENV="production"
if [[ "${ENV}" == "production" ]]; then
echo "프로덕션 환경 — 주의해서 작업하세요"
fi
# 파일/디렉토리 확인
CONFIG="/etc/app/config.yaml"
if [ -f "${CONFIG}" ]; then
echo "설정 파일 존재: ${CONFIG}"
elif [ -d "/etc/app" ]; then
echo "디렉토리는 있지만 설정 파일 없음"
else
echo "디렉토리도 없습니다"
fi
| 숫자 비교 | 의미 | 파일 테스트 | 의미 |
|---|---|---|---|
-eq | 같다 | -f | 파일 존재 |
-ne | 다르다 | -d | 디렉토리 존재 |
-gt | 크다 | -r | 읽기 권한 있음 |
-ge | 크거나 같다 | -w | 쓰기 권한 있음 |
-lt | 작다 | -x | 실행 권한 있음 |
-le | 작거나 같다 | -s | 파일 크기 > 0 |
반복문과 함수
for, while 반복문과 함수를 조합하면 복잡한 자동화 로직을 구현할 수 있습니다.
#!/bin/bash
# 반복문과 함수 예제
# for: 배열 순회
SERVERS=("web01" "web02" "db01" "cache01")
for server in "${SERVERS[@]}"; do
echo "서버 점검: ${server}"
done
# for: 숫자 범위
for i in {1..5}; do
echo "카운트: ${i}"
done
# while: 조건 반복 (파일 한 줄씩 읽기)
while IFS= read -r line; do
echo "읽은 줄: ${line}"
done < /etc/hostname
# 함수 정의와 호출
log() {
local level="$1"
local message="$2"
echo "[$(date '+%H:%M:%S')] [${level}] ${message}"
}
check_service() {
local service="$1"
if systemctl is-active --quiet "${service}"; then
log "INFO" "${service} 정상 실행 중"
return 0
else
log "WARN" "${service} 중지됨"
return 1
fi
}
# 함수 호출
check_service "nginx"
함수 내에서 local 키워드로 지역 변수를 선언하면 함수 밖의 변수에 영향을 주지 않습니다. 함수의 반환값은 return으로 종료 코드(0~255)를 반환하며, 문자열 반환이 필요하면 echo와 $()를 조합합니다.
실전 스크립트: 로그 정리 자동화
지정된 디렉토리에서 오래된 로그 파일을 압축하고 삭제하는 스크립트입니다. 크론잡으로 매일 실행하면 디스크 공간을 자동 관리할 수 있습니다.
#!/bin/bash
# log-cleanup.sh — 로그 파일 정리 자동화
set -euo pipefail # 에러 시 즉시 종료, 미정의 변수 에러, 파이프 에러 전파
LOG_DIR="${1:-/var/log/app}"
DAYS_TO_COMPRESS=7
DAYS_TO_DELETE=30
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
log() { echo "[${TIMESTAMP}] $1"; }
# 디렉토리 확인
if [ ! -d "${LOG_DIR}" ]; then
log "오류: ${LOG_DIR} 디렉토리가 존재하지 않습니다"
exit 1
fi
# 1. 7일 이상 된 로그 → gzip 압축
COMPRESS_COUNT=$(find "${LOG_DIR}" -name "*.log" -mtime +${DAYS_TO_COMPRESS} -type f | wc -l)
if [ "${COMPRESS_COUNT}" -gt 0 ]; then
find "${LOG_DIR}" -name "*.log" -mtime +${DAYS_TO_COMPRESS} -type f -exec gzip {} \;
log "${COMPRESS_COUNT}개 로그 파일 압축 완료"
else
log "압축 대상 없음"
fi
# 2. 30일 이상 된 압축 파일 → 삭제
DELETE_COUNT=$(find "${LOG_DIR}" -name "*.gz" -mtime +${DAYS_TO_DELETE} -type f | wc -l)
if [ "${DELETE_COUNT}" -gt 0 ]; then
find "${LOG_DIR}" -name "*.gz" -mtime +${DAYS_TO_DELETE} -type f -delete
log "${DELETE_COUNT}개 압축 파일 삭제 완료"
else
log "삭제 대상 없음"
fi
# 3. 디스크 사용량 보고
USAGE=$(du -sh "${LOG_DIR}" | awk '{print $1}')
log "현재 로그 디렉토리 크기: ${USAGE}"
set -euo pipefail은 Bash 스크립트의 안전장치로, 프로덕션 스크립트에서는 항상 사용을 권장합니다.
| 옵션 | 효과 |
|---|---|
-e | 명령 실패 시 스크립트 즉시 종료 |
-u | 미정의 변수 사용 시 에러 |
-o pipefail | 파이프라인 중 하나라도 실패하면 전체 실패 |
크론잡 등록 예시: crontab -e에서 0 2 * * * /opt/scripts/log-cleanup.sh /var/log/app >> /var/log/cleanup.log 2>&1 — 매일 새벽 2시에 실행됩니다.
정리
쉘스크립트는 Linux 서버 관리의 필수 도구입니다. 핵심 포인트를 정리하면 다음과 같습니다.
#!/bin/bash로 시작,chmod +x로 실행 권한 부여- 변수
=양쪽 공백 금지, 참조 시${변수}중괄호 권장 - 조건문은
[ ]또는[[ ]], 숫자 비교-eq/-gt, 파일 테스트-f/-d - 함수에서
local로 지역 변수,return으로 종료 코드 반환 set -euo pipefail을 프로덕션 스크립트에 반드시 포함find,awk,grep등 CLI 도구와 조합하면 강력한 자동화 가능