셸 스크립트 (운영 자동화)
6. 연습 문제
문제 1. 인자 검사
첫 인자가 없으면 "사용: 스크립트 <폴더>" 를 내고 종료 코드 2 로 끝내는 한 줄을 쓰세요.
DIR=${1:?사용: $0 <폴더>}:? 는 메시지를 표준 에러로 내고 종료합니다. 종료 코드를 정확히 2 로 하려면 [ $# -ge 1 ] || { echo "사용: $0 <폴더>" >&2; exit 2; } 를 씁니다.
문제 2. 확장 문법
f=/var/log/myapp/app.2026-09-10.log 에서 날짜 2026-09-10 만 뽑는 확장 두 줄을 쓰세요.
d=${f##*app.}
d=${d%.log}앞에서 app. 까지 가장 긴 일치를 지우고, 뒤에서 .log 를 지웁니다. 02 레슨의 sed -E 로도 되지만 확장이 외부 명령 없이 빠릅니다.
문제 3. set -e 함정
다음 스크립트에서 set -e 가 있어도 멈추지 않는 줄을 찾고 이유를 쓰세요.
set -e
grep ERROR app.log | wc -l
cd /nonexistent두 번째 줄입니다. grep 이 실패해도 파이프의 마지막 명령 wc 가 성공이라 전체가 성공입니다. set -o pipefail 을 켜면 멈춥니다. 세 번째 줄은 cd 실패로 멈춥니다.
문제 4. 잠금
같은 스크립트가 동시에 두 번 돌지 않게 하는 코드를 mkdir 방식으로 쓰세요. 스크립트가 어떻게 끝나든 잠금이 풀려야 합니다.
LOCK=/var/run/myjob.lock
mkdir "$LOCK" 2>/dev/null || { echo "이미 실행 중" >&2; exit 1; }
trap 'rmdir "$LOCK"' EXITmkdir 는 있으면 실패하므로 검사와 생성이 한 번에 됩니다. EXIT trap 이 정상·비정상 종료 모두에서 잠금을 지웁니다.
문제 5. 로그 함수
시각, 레벨, 메시지를 찍고 ERROR 는 표준 에러로 보내는 log 함수를 쓰세요.
log() {
local line; line=$(printf '%s [%s] %s' "$(date '+%F %T')" "$1" "$2")
if [ "$1" = ERROR ]; then echo "$line" >&2; else echo "$line"; fi
}local 로 함수 안 변수를 제한합니다. 표준 출력과 에러를 나눠 두면 cron 에서 2>> 로 에러만 따로 모을 수 있습니다.