소개
Linux 명령은 일반적으로 터미널에서 입력을 읽고 결과를 다시 터미널에 출력합니다. 셸을 사용하면 이러한 데이터 스트림을 파일이나 다른 명령에 연결할 수 있습니다. 이를 리디렉션이라고 하며, 로깅, 파이프라인, 백그라운드 작업 및 셸 스크립트의 기반이 됩니다.
이 실습에서는 표준 입력, 표준 출력 및 표준 오류를 사용합니다. >가 파일을 덮어쓰는 경우와 >>가 내용을 추가하는 경우, 2>와 2>&1이 오류를 처리하는 방법, 파이프가 데이터를 전달하는 방법, tee가 동일한 출력을 표시하고 저장하는 방법, /dev/null이 유용한 경우를 배웁니다.
표준 입력, 출력 및 오류 이해하기
이 단계에서는 작은 입력 파일을 만들고 표준 입력을 통해 명령에 연결합니다.
모든 명령은 다음 세 가지 표준 스트림으로 시작합니다.
| 디스크립터 | 이름 | 기본 연결 대상 |
|---|---|---|
0 |
표준 입력 또는 stdin | 키보드 |
1 |
표준 출력 또는 stdout | 터미널 |
2 |
표준 오류 또는 stderr | 터미널 |
작업 디렉터리를 만들고 이동합니다.
mkdir -p /home/labex/project/streams-lab
cd /home/labex/project/streams-lab
here-document 를 사용해 세 줄짜리 입력 파일을 만듭니다. 셸은 두 EOF 표시 사이의 줄을 cat에 입력으로 전달하고, >는 cat의 출력을 input.txt에 저장합니다.
cat > input.txt <<'EOF'
alpha
beta
gamma
EOF
일반적으로 cat input.txt는 파일 이름을 인수로 받습니다. 대신 < 연산자를 사용하면 파일을 디스크립터 0, 즉 표준 입력에 연결할 수 있습니다.
cat < input.txt
세 줄이 출력되어야 합니다. 같은 입력 리디렉션을 줄 수를 세는 wc -l에도 사용합니다.
wc -l < input.txt
출력은 3이어야 합니다. 파일 이름이 wc의 인수가 아니므로 숫자만 출력됩니다.
표준 출력 리디렉션 및 추가
이 단계에서는 일반 명령 출력을 리디렉션하고, 덮어쓰기와 추가의 차이를 확인합니다.
스트림 작업 디렉터리에 있는지 확인합니다.
cd /home/labex/project/streams-lab
> 연산자는 디스크립터 1, 즉 표준 출력을 파일에 연결합니다. 파일이 없으면 만들고, 기존 파일이면 내용을 비운 후 출력 내용을 기록합니다.
echo "Stream report" > report.txt
cat report.txt
다시 덮어쓰기를 실행하여 이전 줄이 사라지는지 확인합니다.
echo "Input lines: 3" > report.txt
cat report.txt
이제 대상 파일을 추가 모드로 여는 >>를 사용합니다.
echo "Status: complete" >> report.txt
cat report.txt
파일에는 정확히 두 줄이 있어야 합니다. 첫 번째 줄은 Input lines: 3, 두 번째 줄은 Status: complete입니다. 리디렉션은 명령이 시작되기 전에 셸이 처리합니다.
표준 출력과 표준 오류 분리하기
이 단계에서는 일반 출력과 오류를 모두 생성하는 명령을 실행한 다음, 각 스트림을 서로 다른 파일에 저장합니다.
다음 ls 명령에는 존재하는 경로와 존재하지 않는 경로가 하나씩 전달됩니다.
cd /home/labex/project/streams-lab
ls -l input.txt missing.txt
input.txt에 대한 정보가 출력되는 줄은 stdout 입니다. No such file or directory 메시지는 stderr 입니다. 기본적으로 두 출력 모두 터미널에 표시되지만, 서로 다른 스트림입니다.
>로 디스크립터 1을 리디렉션하고, 2>로 디스크립터 2를 리디렉션합니다.
ls -l input.txt missing.txt > listing.log 2> errors.log
경로 하나가 없으므로 명령은 여전히 0 이 아닌 종료 상태를 반환합니다. 그러나 셸은 다음 명령을 입력할 수 있는 상태로 유지됩니다. 각 대상 파일의 내용을 확인합니다.
cat listing.log
cat errors.log
listing.log에는 오류 없이 input.txt에 대한 정보가 있어야 합니다. errors.log에는 성공한 목록 정보 없이 missing.txt와 해당 오류가 표시되어야 합니다.
표준 출력과 표준 오류 결합하기
이 단계에서는 stdout 과 stderr 을 하나의 로그에 저장하고, 리디렉션 순서가 중요한 이유를 배웁니다.
먼저 stdout 을 combined.log로 리디렉션한 다음, 디스크립터 2를 디스크립터 1이 현재 사용하는 대상에 연결합니다.
cd /home/labex/project/streams-lab
ls -l input.txt missing.txt > combined.log 2>&1
2>&1은“디스크립터 2 를 현재 디스크립터 1 이 사용하는 것과 같은 대상에 보낸다”는 뜻입니다. > combined.log가 먼저 나오므로 두 스트림 모두 파일에 저장됩니다.
cat combined.log
파일에는 input.txt의 목록 정보와 missing.txt에 대한 오류가 모두 있어야 합니다.
Bash 에서는 두 스트림을 모두 리디렉션하는 축약형으로 &>도 지원합니다.
ls -l report.txt absent.txt &> shorthand.log
cat shorthand.log
이 두 번째 파일에는 성공한 report.txt 목록 정보와 absent.txt에 대한 오류가 모두 있어야 합니다. 이식성이 높은 > file 2>&1 형식은 스크립트와 서비스 명령에서 특히 자주 사용됩니다.
Tee 로 파이프라인 출력 확인하고 저장하기
이 단계에서는 파이프라인과 tee를 사용해 출력을 표시하면서 같은 데이터를 파일에도 저장합니다.
|로 표시하는 파이프는 왼쪽 명령의 stdout 을 오른쪽 명령의 stdin 에 연결합니다. 입력 파일을 알파벳 역순으로 정렬합니다.
cd /home/labex/project/streams-lab
sort -r input.txt
일반 출력 리디렉션을 사용하면 정렬된 줄이 파일로 이동하므로 더 이상 터미널에 표시되지 않습니다.
sort -r input.txt > sorted.txt
cat sorted.txt
tee 명령은 stdin 을 stdout 과 지정한 파일 양쪽에 복사합니다. 파이프를 통해 같은 정렬 명령을 실행합니다.
sort -r input.txt | tee sorted.txt
화면에 정렬된 줄이 표시되고, sorted.txt에도 같은 내용이 저장되어야 합니다. 기본적으로 tee는 >와 마찬가지로 대상 파일을 덮어씁니다.
-a 옵션을 사용하면 tee가 내용을 추가합니다. 한 줄을 더 추가하면서 동시에 표시합니다.
echo "delta" | tee -a sorted.txt
cat sorted.txt
이제 파일에는 gamma, beta, alpha, delta가 있어야 합니다. tee는 터미널에서 실행 결과를 실시간으로 확인하면서 동시에 로그를 저장해야 할 때 유용합니다.
Dev Null 로 불필요한 데이터 버리기
이 단계에서는 /dev/null을 사용해 의도적으로 스트림을 버리고, tee로 유용한 출력을 보존하며, 기존 로그를 비웁니다.
/dev/null은 기록되는 모든 내용을 받아서 버리는 특수 장치입니다. stderr 만 버리면서 실제 디렉터리 하나와 존재하지 않는 디렉터리 하나를 조회합니다.
cd /home/labex/project/streams-lab
ls -l . missing-directory 2> /dev/null
디렉터리 목록은 표시되지만 missing-directory에 대한 오류는 표시되지 않아야 합니다. 여기에 tee를 결합해 화면에 표시되는 stdout 도 저장합니다.
ls -l . missing-directory 2> /dev/null | tee visible-listing.log
파이프에는 stdout 만 전달됩니다. 파이프가 데이터를 받기 전에 stderr 은 별도로 /dev/null로 리디렉션되었습니다.
저장된 목록을 확인합니다.
cat visible-listing.log
마지막으로 임시 로그를 만든 다음, /dev/null을 빈 입력 소스로 사용해 파일 내용을 비웁니다. 별도의 파일에는 4 단계에서 결합한 스트림의 결과가 보존되어 있습니다.
echo "outdated scratch data" > scratch.log
cat /dev/null > scratch.log
파일 크기를 확인합니다.
ls -l scratch.log
파일은 여전히 존재하고 크기는 0바이트여야 합니다. 데이터를 버릴 때는 신중해야 합니다. 실제로 진단 정보가 필요할 때 오류를 숨기면 문제 해결이 더 어려워질 수 있습니다.
요약
세 가지 표준 스트림과 해당 파일 디스크립터를 실습하고, <를 사용해 파일을 stdin 에 연결했으며, >와 >>로 stdout 을 리디렉션했습니다. 2>로 stderr 을 분리하고, 2>&1과 &>를 사용해 stdout 과 결합하면서 연산자 순서가 중요한 이유를 배웠습니다.
또한 일반적인 파일 리디렉션과 파이프라인 및 tee를 비교하고, tee -a를 사용해 출력을 표시하면서 내용을 추가했으며, /dev/null로 불필요한 데이터를 버렸습니다. 이러한 패턴은 이후 과정에서 로깅, 백그라운드 명령 및 셸 스크립트를 이해하는 데 도움이 됩니다.



