command > log.txt로 출력을 저장했는데 에러 메시지는 화면에 그대로 뜬 적 있나요? 이건 버그가 아니라 리눅스가 출력을 두 줄기로 나눠 다루기 때문입니다. 표준 입출력의 핵심은 세 개의 통로와 그 번호입니다.
세 개의 통로와 번호
리눅스의 모든 프로세스는 기본적으로 세 개의 스트림을 엽니다. 각 스트림에는 파일 디스크립터(FD) 번호가 붙어 있고, 리다이렉션은 이 번호를 다루는 일입니다.
| 이름 | FD 번호 | 기본 방향 | 용도 |
|---|---|---|---|
| stdin (표준 입력) | 0 | 키보드 | 프로그램이 받는 입력 |
| stdout (표준 출력) | 1 | 화면 | 정상 결과 |
| stderr (표준 에러) | 2 | 화면 | 에러·진단 메시지 |
정상 결과(stdout)와 에러(stderr)가 별개의 통로라는 게 핵심입니다. >는 사실 1>의 줄임말이라 stdout만 보냅니다. 그래서 에러는 화면에 남는 것입니다.
리다이렉션 기호
>: stdout을 파일로 (덮어쓰기).1>와 같음>>: stdout을 파일에 이어붙이기2>: stderr를 파일로<: 파일을 stdin으로 입력2>&1: stderr를 stdout이 가는 곳으로 합치기
로컬 터미널
ls /tmp /없는경로 > out.txt 2> err.txt
위는 정상 목록은 out.txt로, 에러는 err.txt로 깔끔히 분리합니다. 둘을 한 파일에 합치고 싶을 때 2>&1을 씁니다.
로컬 터미널
command > all.txt 2>&1
이건 "stdout을 all.txt로 보내고(>), 그다음 stderr를 stdout과 같은 곳으로(2>&1)"라는 뜻입니다.
2>&1 순서 함정
2>&1은 "지금 stdout이 향하는 곳"을 복제합니다. 그래서 순서가 결과를 바꿉니다.
로컬 터미널
command 2>&1 > all.txt
이건 의도와 다릅니다. 2>&1을 만난 시점에 stdout은 아직 화면이라 stderr가 화면으로 가고, 그 뒤에야 stdout만 파일로 빠집니다. 반드시 > all.txt를 먼저 쓰고 2>&1을 뒤에 둬야 둘 다 파일로 갑니다.
OUTPUT
# command > all.txt 2>&1 → 정상+에러 모두 all.txt
# command 2>&1 > all.txt → 에러는 화면, 정상만 all.txt
에러 메시지를 아예 버리고 싶으면 2> /dev/null로 /dev/null(블랙홀)에 흘려보냅니다.
요점 정리
- stdin·stdout·stderr는 각각 FD
0·1·2, 정상 출력과 에러는 다른 통로입니다. >는 stdout만 보냄. 에러까지 잡으려면2>또는2>&1.2>&1은 "현재 stdout이 가는 곳"을 복제하므로> 파일뒤에 놓아야 합니다.- 불필요한 출력은
2> /dev/null로 버립니다.
리다이렉션과 파이프를 직접 조합하며 쉘을 손에 익히는 실습은 리눅스 트랙에서 회원가입 없이 무료로 익힐 수 있습니다.