iBetter Books
수정

풀이와 해설

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은 10이 모두 포함되므로 매칭됩니다. 따라서 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)이므로 두 번째 aA로 바뀌어 banAna가 됩니다.

참조: PART 07 sed와 awk

문제 7 — 정답: 1번

NR==3은 현재 처리 중인 레코드(줄) 번호가 3일 때 패턴이 참입니다. -F:는 구분자를 콜론으로 설정합니다. 따라서 3번째 줄의 첫 번째 필드(1)6번째필드(1)와 6번째 필드(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: 소유자에 실행 권한 추가 → rwx
  • g-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)

ssnetstat의 현대적 대체 명령어입니다. -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부터 순서대로 재학습을 권장합니다

오답 패턴을 분석해서 약한 영역을 집중적으로 보완하면 효과적입니다. 단순히 정답을 외우는 것보다 원리를 이해하고 터미널에서 직접 확인하는 것이 오래 기억됩니다.