데이터 스트림 리디렉션

LinuxBeginner
지금 연습하기

소개

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로 불필요한 데이터를 버렸습니다. 이러한 패턴은 이후 과정에서 로깅, 백그라운드 명령 및 셸 스크립트를 이해하는 데 도움이 됩니다.