셸 스크립트 (운영 자동화)
3. 코드 예제
예제 1: 인자·함수·조건 — 01_script_basics.sh 발췌
set -euo pipefail
DRY_RUN=0
while [ $# -gt 0 ]; do
case $1 in
--dry-run) DRY_RUN=1 ;;
-*) echo "모르는 옵션: $1"; usage ;;
*) break ;;
esac
shift
done
WORK=$(mktemp -d); trap 'rm -rf "$WORK"' EXIT
LOG_DIR=${1:-$WORK/logs}
log() { printf '%s [%s] %s\n' "$(date '+%F %T')" "$1" "$2"; }
die() { log ERROR "$1" >&2; exit "${2:-1}"; }
[ -d "$LOG_DIR" ] || die "로그 폴더 없음: $LOG_DIR" 3== 1. 인자: DRY_RUN=0 LOG_DIR=/tmp/tmp.NZMlGRHSNm/logs
2026-09-10 16:55:43 [INFO] 시작
파일 있음
비어 있지 않음
5 > 3 (숫자는 -gt -lt -eq)
패턴 일치 (문자열은 == != 와 글로브)bash 01_script_basics.sh --bad 를 치면 "모르는 옵션" 과 사용법이 나오고 종료 코드 2 입니다. 잘못된 호출을 첫 줄에서 막는 것이 옵션 파서의 역할입니다.
예제 2: 변수 확장 — 01_script_basics.sh 발췌
path=/opt/myapp/releases/app-1.2.3.jar
echo "${path##*/}"
echo "${path%/*}"
ver=${path##*app-}; ver=${ver%.jar}; echo "버전=$ver"
echo "${UNSET_VAR:-기본값}"
arr=(a b c); echo "배열 ${#arr[@]}개, 두 번째=${arr[1]}"app-1.2.3.jar
/opt/myapp/releases
버전=1.2.3
기본값
배열 3개, 두 번째=b두 번에 나눠 자르면 파일명에서 버전만 뽑힙니다. 배포 스크립트가 jar 이름으로 릴리스 폴더 이름을 정할 때 이 방식을 씁니다.
예제 3: 종료 코드와 trap — 01_script_basics.sh 발췌
if grep -q ERROR "$f"; then echo "에러 있음"; else echo "에러 없음"; fi
set +e; false; rc=$?; set -e; echo "종료 코드=$rc"
trap 'echo " ERR trap: 줄 $LINENO 에서 실패"' ERR
set +e; ls "$WORK/없는폴더" 2>/dev/null; set -e
ls "$WORK/없는폴더" 2>/dev/null || echo " || 뒤는 조건 문맥"에러 없음 (grep 종료 코드 1 을 if 가 처리)
실패 명령 종료 코드=1 (set +e 로 잠시 허용)
ERR trap: 줄 71 에서 실패
|| 뒤는 조건 문맥이라 trap 도 set -e 도 안 걸린다같은 ls 실패가 단독으로는 ERR trap 을 부르고 || 뒤에서는 부르지 않습니다. 이 차이를 알면 set -e 가 "왜 안 멈추지" 와 "왜 멈추지" 둘 다 설명됩니다.
예제 4: 잠금과 dry run — 01_script_basics.sh 발췌
LOCK=$WORK/script.lock
mkdir "$LOCK" 2>/dev/null || die "이미 실행 중 (lock: $LOCK)"
trap 'rm -rf "$LOCK" "$WORK"' EXIT
run rm -f "$f.bak" lock 획득
[dry] rm -f /tmp/tmp.YWXf4lbZnl/logs/app.log.bak
2026-09-10 16:55:56 [INFO] 완료--dry-run 으로 실행하면 rm 이 실제로 돌지 않고 출력만 됩니다. 05 레슨의 배포 스크립트가 같은 run 함수를 씁니다.