모든 프로그램에 열리는 세 가지 통로
Unix 프로세스는 시작할 때 세 개의 파일 디스크립터를 받아. stdin(0)은 입력, stdout(1)은 결과, stderr(2)는 오류와 진단을 내보내는 통로야. 셸의 파이프와 리디렉션은 이 통로가 어디를 가리키는지 바꾸는 기능이야.
처음 연결되는 곳
- stdin (0): 보통 키보드에서 읽어.
- stdout (1): 보통 터미널 화면에 결과를 써.
- stderr (2): 화면에 보이지만 stdout과 분리돼 있어. 오류 메시지가 다음 명령으로 넘길 데이터에 섞이지 않게 해.
왜 출력 통로가 둘일까?
find / -name foo 2>/dev/null | grep bar에서 권한 오류는 stderr로 나가 버려지고, 실제 검색 결과만 stdout을 따라 grep으로 들어가. 출력 통로가 하나뿐이라면 진단과 데이터를 따로 처리할 수 없어.
파일 디스크립터 번호로 연결하기
2>는 stderr, 1>는 stdout을 뜻해. 2>&1은 stderr가 현재 stdout과 같은 목적지를 가리키게 해. 필요하면 exec 3> file로 3번 디스크립터를 열고 printf 'hello\n' >&3처럼 별도 출력 통로를 만들 수도 있어.
스트림은 형식이 아니라 통로야
stdin, stdout, stderr는 바이트가 흐르는 경로일 뿐 UTF-8이나 줄 단위 텍스트를 보장하지 않아. 다음 명령이 특정 형식을 기대한다면 앞 명령이 그 계약을 실제로 내보내는지 확인해야 해. 바이너리를 텍스트 도구로 넘기면 조용히 손상될 수 있어.
표준 오류를 분리하면 조합하기 쉬워
결과 데이터는 stdout으로, 진행 상황과 진단은 stderr로 보내. 그러면 호출자는 결과만 파일에 저장하거나 다음 명령으로 넘길 수 있어. 직접 만든 스크립트도 이 약속을 지켜야 파이프라인에서 안전하게 재사용할 수 있어. 결과와 진단을 한 통로에 섞으면 호출자가 문자열을 다시 해석해야 하고, 그 순간 조합 가능한 인터페이스가 사람 눈에만 맞는 출력으로 퇴보해.