풀이와 해설
1회차부터 3회차까지 총 60문제의 정답과 해설입니다. 정답만 확인하지 말고, 틀린 문제는 해설을 꼼꼼히 읽고 관련 PART를 다시 복습하기를 권장합니다.
1회차 풀이
문제 1 — 정답: 2번 ($0)
$0은 현재 실행 중인 스크립트의 파일명을 담고 있습니다. $#은 인수 개수, $1은 첫 번째 위치 매개변수, $$는 현재 쉘 PID입니다.
참조: PART 03 쉘 스크립트 기초
문제 2 — 정답: 2번 (35)
$((...)) 산술 확장으로 계산합니다. 10 * 3 = 30, 30 + 5 = 35입니다.
참조: PART 03 쉘 스크립트 기초
문제 3 — 정답: 2번 ([ -z "$VAR" ])
-z는 문자열 길이가 0(zero)일 때 참입니다. -n은 길이가 0이 아닐 때 참입니다. -f와 -e는 파일 관련 옵션입니다.
참조: PART 04 조건문과 반복문
문제 4 — 정답: 3번 (if [ $i -eq 3 ]; then continue; fi)
continue는 현재 반복을 건너뛰고 다음 반복으로 넘어갑니다. break는 루프 전체를 종료합니다. exit은 스크립트 자체를 종료하고, return은 함수 내에서만 사용합니다.
참조: PART 04 조건문과 반복문
문제 5 — 정답: 2번 (750)
rwx(7) r-x(5) ---(0)이므로 750입니다. 755는 rwxr-xr-x, 740은 rwxr-----, 760은 rwxrw----입니다.
참조: PART 02 리눅스 기본 명령어
문제 6 — 정답: 3번 (640)
파일 기본 권한 666에서 umask 027을 빼면 640(rw-r-----)이 됩니다. umask 022라면 644가 됩니다.
참조: 이 PART 01장 02절
문제 7 — 정답: 2번 (2)
wc -w는 단어 수를 셉니다. "hello world"는 두 단어이므로 2를 출력합니다. wc -c는 문자(바이트) 수, wc -l은 줄 수입니다.
참조: PART 02 리눅스 기본 명령어
문제 8 — 정답: 2번 (command 2>/dev/null > file.txt)
표준 오류(2)를 /dev/null로 버리고 표준 출력(1)을 파일로 저장합니다. 3번 > file.txt 2>&1은 표준 출력과 오류 모두를 파일로 저장합니다.
참조: PART 02 리눅스 기본 명령어
문제 9 — 정답: 2번 (3)
${#배열[@]}는 배열 원소의 개수를 반환합니다. FRUITS 배열에 세 원소가 있으므로 3을 출력합니다.
참조: PART 05 함수와 배열
문제 10 — 정답: 2번 (cut -d: -f1 /etc/passwd)
cut -d:는 콜론을 구분자로 지정하고, -f1은 첫 번째 필드를 선택합니다.
오답 분석.
- 1번: grep의
-f옵션은 패턴 파일을 지정하는 옵션입니다. - 3번:
-c1은 첫 번째 문자(한 글자)만 출력합니다. - 4번: awk 패턴이 잘못되었습니다.
/etc/passwd단어가 있는 줄을 찾는 것이므로 의도한 동작이 아닙니다.
참조: PART 02 리눅스 기본 명령어
문제 11 — 정답: 2번 (디렉토리일 때)
-d는 디렉토리 여부를 확인합니다. -f는 일반 파일, -r은 읽기 권한, -e는 모든 종류의 파일 존재 여부를 확인합니다.
참조: PART 04 조건문과 반복문
문제 12 — 정답: 2번 (가, 나)
명령어 치환은 $(명령어) 또는 역따옴표(`명령어`)를 사용합니다. {date}는 변수 확장 문법이 아니고, $[date]는 구식 산술 확장 문법입니다.
참조: PART 03 쉘 스크립트 기초
문제 13 — 정답: 3번 (third 한 줄)
>는 파일을 덮어씁니다. >>는 파일 끝에 추가합니다. 순서대로 실행하면 먼저 "first"로 생성, "second"를 추가(두 줄), 다시 "third"로 덮어씁니다. 최종적으로 "third" 한 줄만 남습니다.
참조: PART 02 리눅스 기본 명령어
문제 14 — 정답: 2번
Bash 함수의 return은 0~255 범위의 정수(종료 코드)만 반환합니다. 문자열을 반환하려면 echo로 출력하고 명령어 치환($(함수명))으로 받아야 합니다.
참조: PART 05 함수와 배열
문제 15 — 정답: 1번 (find /home -name "*.log" -mtime -7)
-mtime -7은 최근 7일 이내에 수정된 파일을 의미합니다. -mtime +7은 7일 이전입니다. +는 초과, -는 미만입니다.
참조: 이 PART 01장 02절
문제 16 — 정답: 3번 (동일한 inode 공유)
하드링크는 같은 inode를 가리키므로 원본을 삭제해도 다른 하드링크로 접근할 수 있습니다. 다른 파티션의 파일은 하드링크로 연결할 수 없습니다. 디렉토리 하드링크는 root만 제한적으로 사용할 수 있습니다.
참조: PART 02 리눅스 기본 명령어
문제 17 — 정답: 2번 (HELLO WORLD)
tr '[:lower:]' '[:upper:]'는 소문자를 대문자로 변환합니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 18 — 정답: 2번
while 루프의 올바른 형식은 while 조건; do 명령어; done입니다. do 앞에 반드시 세미콜론 또는 줄바꿈이 있어야 합니다.
참조: PART 04 조건문과 반복문
문제 19 — 정답: 2번 (5줄)
[246810]은 문자 클래스로 2, 4, 6, 8, 1, 0 중 하나라도 포함된 줄을 찾습니다. seq 1 10 중에서 해당하는 숫자는 2, 4, 6, 8, 10입니다. 10은 1과 0이 모두 포함되므로 매칭됩니다. 따라서 5줄이 출력됩니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 20 — 정답: 2번
set -e는 명령어가 0이 아닌 종료 코드를 반환하면 스크립트를 즉시 종료합니다. set -u는 미선언 변수 사용 시 오류, set -o pipefail은 파이프라인 오류 감지, set -x는 실행 추적 모드입니다.
참조: PART 11 견고한 스크립트 작성
2회차 풀이
문제 1 — 정답: 2번 (grep "^root" /etc/passwd)
^는 줄의 시작을 의미하는 정규표현식 앵커입니다. ^root는 "root로 시작하는 줄"을 매칭합니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 2 — 정답: 2번 (2024)
-o 옵션은 매칭된 부분만 출력하고, -E는 확장 정규표현식을 사용합니다. [0-9]{4}는 연속된 숫자 4자리와 매칭됩니다. 첫 번째 4자리 숫자 2024만 출력됩니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 3 — 정답: 3번
sed 's/foo/bar/g'에서 g 플래그는 전역 치환(global)을 의미합니다. 결과는 표준 출력으로 나오며, 원본 파일을 수정하려면 -i 옵션이 필요합니다.
참조: PART 07 sed와 awk
문제 4 — 정답: 2번 (30 alice)
awk에서 $1은 첫 번째 필드, $2는 두 번째 필드입니다. {print $2, $1}이므로 alice(1번)와 30(2번)의 순서가 바뀌어 30 alice가 출력됩니다.
참조: PART 07 sed와 awk
문제 5 — 정답: 2번 (.+)
ERE에서 .은 임의의 한 문자, +는 1회 이상 반복을 의미합니다. 따라서 .+는 한 글자 이상의 임의 문자열입니다. .*는 0회 이상, .?는 0 또는 1회입니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 6 — 정답: 1번 (bAnana)
s/a/A/2의 숫자 플래그 2는 두 번째 발생만 치환합니다. "banana"에서 a가 처음 나오는 곳은 2번째 문자(banana), 두 번째는 4번째 문자(banana)이므로 두 번째 a가 A로 바뀌어 banAna가 됩니다.
참조: PART 07 sed와 awk
문제 7 — 정답: 1번
NR==3은 현재 처리 중인 레코드(줄) 번호가 3일 때 패턴이 참입니다. -F:는 구분자를 콜론으로 설정합니다. 따라서 3번째 줄의 첫 번째 필드(6)를 출력합니다.
참조: PART 07 sed와 awk
문제 8 — 정답: 1번 (3)
printf "one\ntwo\nthree\n"은 줄바꿈으로 구분된 세 줄을 출력합니다. wc -l은 줄 수를 세므로 3이 됩니다.
참조: PART 02 리눅스 기본 명령어
문제 9 — 정답: 1번 (sed '/^$/d' file.txt)
/^$/는 시작(^)과 끝($)이 바로 붙어있는 빈 줄을 매칭하고, d는 해당 줄을 삭제합니다.
참조: PART 07 sed와 awk
문제 10 — 정답: 2번 (2줄)
^a는 a로 시작하는 줄을 매칭합니다. apple과 apricot 두 줄이 해당됩니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 11 — 정답: 4번 (awk '{last=$0} END {print last}' file.txt)
awk의 END 블록은 파일을 모두 처리한 후 실행됩니다. 1번의 END {print $0}은 END 블록에서 $0이 비어있어 동작하지 않습니다. 매 줄마다 last에 저장하고 END에서 출력하는 4번이 올바릅니다.
참조: PART 07 sed와 awk
문제 12 — 정답: 2번 (Hll Wrld)
tr -d는 지정한 문자를 삭제합니다. 모음(a, e, i, o, u 대소문자 모두)을 삭제하면 Hll Wrld가 됩니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 13 — 정답: 2번 (grep -i)
-i는 case-insensitive로 대소문자를 구분하지 않습니다. -c는 매칭 줄 수, -n은 줄 번호 표시, -v는 매칭되지 않는 줄 출력입니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 14 — 정답: 3번
sed -n은 기본 출력을 억제하고, p 플래그가 있는 줄만 출력합니다. 2,5p는 2번째 줄부터 5번째 줄까지 출력합니다.
참조: PART 07 sed와 awk
문제 15 — 정답: 3번 (150)
NF는 현재 레코드의 필드 수입니다. "10 20 30 40 50"에서 NF는 5입니다. for 루프로 모든 필드를 더하면 10+20+30+40+50 = 150이 됩니다.
참조: PART 07 sed와 awk
문제 16 — 정답: 2번 (010-[0-9]{4}-[0-9]{4})
010은 고정, [0-9]{4}는 숫자 4자리, -는 하이픈입니다. 1번은 010 앞자리를 고정하지 않습니다. 3번은 사이 내용을 무시하는 느슨한 패턴입니다. 4번의 \d는 grep의 기본 BRE에서 지원되지 않고 Perl 정규표현식에서 사용합니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 17 — 정답: 2번 ([a][b][c][d])
\(.\)는 임의의 한 문자를 캡처하고, \1은 그것을 역참조합니다. 따라서 \(.\)\1은 같은 문자가 연속으로 두 번 나오는 패턴을 매칭합니다. "aabbccdd"에서 aa, bb, cc, dd 각각이 매칭되어 [a][b][c][d]로 치환됩니다.
참조: PART 07 sed와 awk
문제 18 — 정답: 3번 (set -o pipefail)
set -o pipefail은 파이프라인에서 중간 명령어가 실패하면 파이프라인 전체가 실패한 것으로 처리합니다. set -e는 명령어 실패 시 종료, set -u는 미선언 변수 오류, set -x는 실행 추적입니다.
참조: PART 11 견고한 스크립트 작성
문제 19 — 정답: 1번 (짝수 번째 줄)
NR % 2 == 0은 줄 번호를 2로 나눈 나머지가 0인 경우, 즉 짝수 번째 줄에 해당합니다. 기본적으로 패턴만 지정하면 매칭되는 줄을 출력합니다.
참조: PART 07 sed와 awk
문제 20 — 정답: 3번 (exit: 2, 오류 메시지 없이)
2>/dev/null은 표준 오류를 버립니다. ls /nonexistent는 존재하지 않는 경로이므로 종료 코드 2를 반환하지만 오류 메시지는 /dev/null로 사라집니다. $?는 직전 명령의 종료 코드이므로 exit: 2가 출력됩니다.
참조: PART 02 리눅스 기본 명령어, PART 11 견고한 스크립트 작성
3회차 풀이
문제 1 — 정답: 1번
*/15 9-17 * * 1-5를 분석합니다. 분 필드 */15는 15분마다, 시 필드 9-17은 9시부터 17시까지, 요일 1-5는 월요일부터 금요일까지입니다. 따라서 평일 오전 9시부터 오후 5시까지 15분마다 실행됩니다.
참조: 이 PART 01장 03절
문제 2 — 정답: 2번 (rwxr--r--)
초기 권한 rw-rw-rw-에서 시작합니다.
u+x: 소유자에 실행 권한 추가 →rwxg-w: 그룹에서 쓰기 권한 제거 →r--o=r: 기타를 읽기만으로 설정 →r--결과:rwxr--r--
참조: 이 PART 01장 02절
문제 3 — 정답: 2번
while IFS= read -r line은 파일의 각 줄을 읽어 변수에 저장합니다. < /etc/passwd로 입력 리다이렉션하여 파일을 줄 단위로 읽고, 반복마다 count를 1씩 증가시킵니다. 실행 결과는 /etc/passwd의 실제 줄 수입니다.
참조: PART 04 조건문과 반복문
문제 4 — 정답: 2번
D 상태(Uninterruptible Sleep)는 주로 디스크 I/O나 네트워크 파일시스템 대기 중인 프로세스입니다. 이 상태에서는 시그널로 종료할 수 없어 시스템 관리에서 주의가 필요합니다.
참조: PART 08 프로세스와 시그널
문제 5 — 정답: 1번
$$는 현재 쉘의 PID를 담고 있습니다. /proc/$$는 현재 쉘 프로세스의 /proc 디렉토리를 가리킵니다. head -1로 첫 줄만 출력합니다.
참조: PART 08 프로세스와 시그널
문제 6 — 정답: 3번
SIGHUP(1번)은 원래 터미널 연결이 끊겼을 때 보내는 시그널이었지만, 많은 데몬 프로세스에서 이 시그널을 설정 파일 재로드 신호로 재정의하여 사용합니다. nginx -s reload가 내부적으로 SIGHUP을 사용합니다.
참조: PART 08 프로세스와 시그널
문제 7 — 정답: 2번
trap cleanup EXIT는 스크립트가 어떤 방식으로 종료되든(정상 종료, 오류 종료, 시그널 수신) cleanup 함수를 실행합니다. 이것이 임시 파일 정리 패턴의 핵심입니다.
참조: PART 08 프로세스와 시그널
문제 8 — 정답: 2번 (ss -tuln)
ss는 netstat의 현대적 대체 명령어입니다. -t(TCP), -u(UDP), -l(LISTEN), -n(숫자 형식)으로 수신 대기 중인 포트를 확인합니다.
참조: 이 PART 01장 04절
문제 9 — 정답: 2번 (200)
"100 200 300"에서 필드 합계는 600이고, NF(필드 수)는 3입니다. 600/3 = 200입니다.
참조: PART 07 sed와 awk
문제 10 — 정답: 3번
/etc/hosts는 호스트명과 IP 주소의 정적 매핑을 담고 있습니다. DNS 조회보다 먼저 참조됩니다. DNS 서버 주소는 /etc/resolv.conf에 설정합니다.
참조: 이 PART 01장 04절
문제 11 — 정답: 2번 (6)
tee는 표준 입력을 파일과 표준 출력 양쪽으로 보냅니다. "Hello\n"은 6바이트(H, e, l, l, o, 줄바꿈)입니다. wc -c는 바이트 수를 세므로 6이 출력됩니다. "Hello"는 /tmp/out.txt에도 저장됩니다.
참조: PART 02 리눅스 기본 명령어
문제 12 — 정답: 1번
&&는 앞 명령이 성공(종료 코드 0)일 때만 뒷 명령을 실행합니다. systemctl restart nginx가 성공하면 systemctl status nginx로 상태를 확인합니다.
참조: 이 PART 01장 03절
문제 13 — 정답: 3번
declare -r은 읽기 전용 변수를 선언합니다. 이미 선언된 읽기 전용 변수에 값을 재할당하면 오류 메시지가 출력되고 해당 줄이 무시됩니다. 스크립트 자체는 계속 실행됩니다 (단, set -e가 설정된 경우 종료될 수 있습니다).
참조: PART 03 쉘 스크립트 기초
문제 14 — 정답: 3번 (find / -type f -perm /4000)
-perm /4000은 SetUID 비트가 설정된 파일을 찾습니다. /는 특정 비트가 설정된 경우를 의미합니다. -type f를 추가하여 일반 파일만 대상으로 합니다. 4번의 -perm +4000은 구식 문법입니다.
참조: 이 PART 01장 02절
문제 15 — 정답: 2번 (world 1)
./script.sh hello world로 실행하면 $1=hello, $2=world, $#=2입니다. shift를 실행하면 위치 매개변수가 왼쪽으로 한 칸 이동하여 $1=world, $#=1이 됩니다. 따라서 $1 $#는 world 1을 출력합니다.
참조: PART 03 쉘 스크립트 기초
문제 16 — 정답: 1번
here document는 << 리다이렉션 연산자로 시작하고, 지정한 종료 문자열(여기서는 EOF)로 끝납니다. 마지막 EOF는 줄의 맨 앞에 위치해야 합니다.
cat << EOF여러 줄의 텍스트EOF
참조: PART 03 쉘 스크립트 기초
문제 17 — 정답: 1번
grep "$TODAY" /var/log/syslog로 오늘 날짜가 있는 줄을 필터링하고, 다시 grep -c "error"로 error가 포함된 줄 수를 셉니다.
참조: PART 06 텍스트 처리와 정규표현식
문제 18 — 정답: 1번
$PIPESTATUS는 파이프라인에서 각 명령어의 종료 코드를 배열로 저장합니다. ${PIPESTATUS[@]}로 전체 배열을 출력하면 각 단계의 종료 코드를 개별로 확인할 수 있습니다.
참조: PART 11 견고한 스크립트 작성
문제 19 — 정답: 3번
( echo "line1"; echo "line2" )는 서브쉘에서 두 줄을 출력합니다. >로 /tmp/test.txt에 저장하면 두 줄이 저장됩니다. 이후 >>로 "line3"을 추가하므로 최종적으로 세 줄이 저장됩니다.
참조: PART 02 리눅스 기본 명령어
문제 20 — 정답: 2번
source ./functions.sh 또는 축약형 . ./functions.sh는 지정한 파일을 현재 쉘 환경에서 실행합니다. 파일에 정의된 함수와 변수가 현재 쉘에서 사용 가능해집니다.
참조: PART 05 함수와 배열
점수 분석
| 점수 | 수준 | 다음 단계 |
|---|---|---|
| 55~60점 | 우수 | 실기 시험 대비로 넘어가도 됩니다 |
| 45~54점 | 양호 | 틀린 문제의 PART를 복습합니다 |
| 35~44점 | 보통 | 1회차부터 다시 풀고 해설을 정독합니다 |
| 34점 이하 | 기초 보완 필요 | PART 01부터 순서대로 재학습을 권장합니다 |
오답 패턴을 분석해서 약한 영역을 집중적으로 보완하면 효과적입니다. 단순히 정답을 외우는 것보다 원리를 이해하고 터미널에서 직접 확인하는 것이 오래 기억됩니다.