Devin.KR

터미널과 파일 기록

100분 안팎

학습 목표

경로·권한·표준 출력·오류·종료 상태를 확인하고 실습 폴더에 기록합니다.

개념

명령을 쳤다는 사실과 기록을 남겼다는 사실

장애 조사 중 터미널에 성공 메시지가 보였더라도 다음 담당자가 같은 조건으로 재현하지 못하면 증거가 부족합니다. 이 레슨에서는 학교망 점검 결과를 파일에 남기는 셸의 기본 동작을 익힙니다. 실제 네트워크를 건드리지 않고 작은 모의 진단 프로그램을 사용합니다. 프로그램은 단말 한 행을 정상 출력으로 보내고, 없는 단말에 대한 설명을 오류 출력으로 보낸 뒤 상태 2로 끝납니다. 일부 결과를 얻었어도 전체 작업은 실패할 수 있다는 상황입니다.

터미널은 명령을 입력하는 화면이고 셸은 그 명령을 해석하는 프로그램입니다. 여기서는 Bash로 실행하는 스크립트를 제공합니다. 현재 폴더를 기준으로 evidence/stdout.txt를 만들면 실행 위치가 달라질 때 다른 곳에 저장됩니다. 명령을 실행하기 전에 pwd로 위치를 확인하고 ls로 파일 이름을 봅니다. 압축을 푼 루트에는 check.sh와 record.sh가 함께 있어야 합니다. 파일이 없다는 오류를 권한 문제로 먼저 해석하지 않습니다.

경로를 읽고 기록 폴더를 만듭니다

상대 경로 evidence는 현재 폴더 아래이고, ../evidence는 한 단계 위 폴더 아래입니다. 절대 경로는 루트에서 시작해 위치를 지정합니다. cd는 셸의 현재 폴더를 바꾸지만 다른 터미널 창의 위치를 바꾸지는 않습니다. 다운로드 폴더에서 실습 폴더로 옮긴 뒤 다시 pwd를 확인하는 습관을 들입니다. 파일 이름에 공백이 있다면 경로를 큰따옴표로 감싸 인자를 하나로 전달합니다.

mkdir -p evidence backup은 두 폴더가 이미 있어도 사용할 수 있도록 만듭니다. 새 파일을 저장하려는 상위 폴더가 없으면 출력 리디렉션 자체가 실패할 수 있습니다. “No such file or directory”가 파일 이름 뒤에 보이면 파일을 여는 단계부터 확인합니다. 프로그램 내부 처리까지 시작했는지 구별해야 하며, 없는 폴더를 만들기 위해 관리자 권한을 요청하는 방식은 원인을 해결하지 못합니다.

실습 검사기는 원본 폴더를 덮어쓰지 않고 임시 폴더에 record.sh를 복사해 실행합니다. 검사 종료 시 그 임시 폴더를 정리합니다. 따라서 check.sh 성공만으로 원본 evidence 폴더가 생겼다고 기대하지 않습니다. 실제 산출물을 눈으로 보고 싶다면 자신의 실습 폴더에서 bash record.sh를 따로 실행합니다. 실험용 임시 결과와 인계할 기록을 구별하면 성공 파일을 잘못 찾는 일을 줄일 수 있습니다.

표준 출력과 표준 오류를 분리합니다

표준 출력은 프로그램이 제공하는 결과이고 표준 오류는 진단 설명을 위한 별도 통로입니다. 두 통로 모두 기본적으로 같은 터미널에 표시될 수 있으므로 화면만 보면 구분이 흐려집니다. >는 표준 출력을 파일로, 2>는 표준 오류를 파일로 보냅니다. 예제에서 stdout.txt에는 student,s1 한 행만, stderr.txt에는 missing: ghost 한 행만 있어야 합니다. 오류 설명이 CSV 데이터에 섞이면 다음 프로그램이 잘못된 단말로 읽을 수 있습니다.

>는 기존 파일 내용을 교체하고 >>는 뒤에 덧붙입니다. 점검을 두 번 실행했는데 예전 오류가 그대로 쌓여 있으면 현재 실행의 실패로 오해할 수 있습니다. 이 실습은 실행 한 번의 결과를 비교하므로 덮어쓰기를 사용합니다. 실제 반복 점검을 누적할 때는 시점과 대상도 함께 써서 어느 실행인지 구별합니다. 단지 덧붙이기를 선택했다고 실행 경계가 자동으로 기록되지는 않습니다.

표준 출력을 버렸는데 오류가 화면에 남는다고 명령이 이상한 것은 아닙니다. 서로 다른 통로이기 때문입니다. 반대로 오류 통로를 버리면 종료 상태가 실패인 이유를 찾을 수 없습니다. 네트워크 명령이 긴 결과를 낼 때도 먼저 정상 결과와 진단 메시지를 각각 보존한 뒤 필요한 줄을 추립니다. 실패 원인을 감추기 위해 2>/dev/null을 붙이는 습관은 이후 검증을 어렵게 만듭니다.

종료 상태는 다음 명령이 덮어씁니다

Bash의 $?는 바로 직전에 끝난 명령의 종료 상태입니다. 0은 성공을 뜻하며 0이 아닌 값은 해당 프로그램이 실패나 다른 조건을 나타내는 데 사용합니다. 구체적인 숫자의 의미는 도구마다 다릅니다. 이 예제에서 2를 선택한 이유는 제공 코드의 sys.exit(2) 때문입니다. 실제 curl이나 ping의 상태 2도 같은 종류의 오류라는 뜻은 아닙니다. 도구 설명과 표준 오류를 함께 읽습니다.

진단 뒤에 echo를 먼저 실행하고 $?를 저장하면 echo의 상태가 들어갑니다. 그래서 status=$?를 실패한 명령 바로 다음에 둡니다. set -e를 사용한 스크립트에서는 단순 실패가 이후 기록 전에 실행을 중단할 수 있으므로 if 명령; then ... else ... fi 형태로 실패를 처리합니다. else 안에서 최초로 상태를 저장한 뒤 파일을 씁니다. 이 방식은 실패를 성공으로 바꾸지 않고 보고서를 만들 기회를 확보합니다.

검사 명령의 성공과 진단 대상의 성공도 분리합니다. record.sh는 진단이 실패했다는 상태를 파일에 정확히 저장하면 자신의 기록 작업을 성공적으로 끝낼 수 있습니다. check.sh는 파일 내용이 계약과 같으면 0을 돌려줍니다. 진단 상태 파일에 2가 있는데 검사기가 PASS를 출력하는 것은 모순이 아닙니다. 검사 대상이 연결 성공이 아니라 실패 기록의 정확성이기 때문입니다.

권한과 백업을 눈으로 검증합니다

chmod 600 evidence/stdout.txt는 파일 소유자에게 읽기·쓰기를 허용하고 그룹과 다른 사용자에게는 권한을 주지 않습니다. 숫자의 각 자리는 소유자·그룹·기타를 뜻하며 읽기 4, 쓰기 2, 실행 1을 더합니다. 600은 문서 파일의 읽기·쓰기 권한 예시입니다. 700은 소유자 실행도 포함하므로 같은 의미가 아닙니다. 디렉토리의 실행 권한은 그 안으로 접근하는 의미라 파일 권한과 함께 생각해야 합니다.

스크립트는 bash record.sh로 실행하므로 파일 자체에 실행 비트가 없어도 Bash가 읽을 수 있으면 실행합니다. ./record.sh로 직접 실행하려면 실행 권한과 적절한 첫 줄이 필요합니다. “Permission denied”를 보면 어떤 파일을 어떤 방식으로 열었는지 확인합니다. 파일이 다른 사용자 소유인지, 상위 폴더를 통과할 수 있는지도 봅니다. 실습을 편하게 하려고 모든 파일에 777을 주는 선택은 기록의 보호 범위를 없앱니다.

cp로 만든 backup/stdout.txt는 복사 시점의 별도 파일입니다. 내용이 같은지 비교해야 백업이 올바른 대상을 복사했는지 알 수 있습니다. 같은 폴더에서 다른 이름으로 복사하는 이번 연습은 디스크 손상 대비 백업까지 제공하지는 않습니다. 뒤의 변경 모듈에서는 보관 위치와 복구 시험을 확장합니다. 여기서는 원본과 복사본의 바이트가 같은지, 실패 상태가 보존됐는지, 권한이 의도한 값인지 다섯 기준을 확인합니다.

따라하기

폴더 위치 확인

따라하기 명령은 자신의 빈 연습 폴더에서 실행합니다. 현재 위치의 마지막 폴더 이름과 하위 폴더를 확인합니다.

mkdir -p school-lab/evidence
cd school-lab
printf 'folder=%s\n' "${PWD##*/}"
ls

실행 결과

folder=school-lab
evidence

실패한 진단 기록

오류를 숨기지 않고 두 통로와 상태를 읽습니다. 출력의 마지막 행은 오류 파일을 cat으로 읽은 결과입니다.

mkdir -p evidence
if python3 -c 'import sys; print("student,s1"); print("missing: ghost", file=sys.stderr); sys.exit(2)' >evidence/stdout.txt 2>evidence/stderr.txt; then
  status=0
else
  status=$?
fi
printf 'status=%s\n' "$status"
cat evidence/stdout.txt
cat evidence/stderr.txt

실행 결과

status=2
student,s1
missing: ghost

권한과 복사본 비교

Python은 파일 모드를 운영체제별 ls 표시 차이 없이 확인하는 용도로만 사용합니다.

mkdir -p evidence backup
printf 'student,s1\n' >evidence/stdout.txt
chmod 600 evidence/stdout.txt
cp evidence/stdout.txt backup/stdout.txt
python3 -c 'from pathlib import Path; p=Path("evidence/stdout.txt"); print("mode:", oct(p.stat().st_mode & 0o777)); print("same:", p.read_bytes()==Path("backup/stdout.txt").read_bytes())'

실행 결과

mode: 0o600
same: True

다운로드 실습 검사

network-shell-records starter.zip 루트에서 record.sh의 상태 저장과 권한을 고칩니다. 다음은 solution에서 직접 실행한 검사 결과이며 starter에서는 일부 기준이 실패해야 합니다.

bash check.sh

실행 결과

PASS: 5 file checks

확인 문제

실습

record.sh에서 실패 상태 2를 보존하고 evidence/stdout.txt를 600으로 만듭니다. 정상 출력·오류·상태를 각각 파일로 저장하고 backup/stdout.txt의 내용을 원본과 일치시킵니다. 검사기는 임시 폴더에서 5개 기준을 확인합니다. 모의 진단 코드와 check.sh는 바꾸지 않습니다.

시작 코드·테스트 내려받기

실행 명령

bash check.sh

기대 결과

PASS: 5 file checks

모범 답안모범 답안 내려받기

더 읽기

면접 질문

  • 진단 명령의 종료 상태와 검사기의 종료 상태를 어떻게 구별하나요?
  • 변경 전 기록을 남길 때 표준 출력과 표준 오류를 어떻게 보존하나요?