파이프가 기본으로 옮기지 않는 스트림
파이프는 stdout만 다음 명령으로 보내. 뒤에 |가 몇 개 이어져도 stderr는 기본적으로 화면에 남아. 오류를 파일에 저장하거나 숨기거나 파이프에 넣으려면 stderr의 목적지를 명시적으로 바꿔야 해.
자주 쓰는 세 가지 형태
cmd 2> err.log: stderr를 파일에 써.cmd 2>/dev/null: stderr를 버려.cmd 2>&1: stderr가 stdout의 현재 목적지를 가리키게 해.
cmd 2>&1 | grep ERROR는 두 출력 스트림에서 ERROR를 찾고, cmd > out.log 2>&1는 두 스트림을 한 파일에 저장해.
리디렉션 순서가 결과를 바꿔
셸은 리디렉션을 왼쪽부터 적용하고 &1을 만난 순간의 1번 파일 디스크립터 목적지를 복제해.
cmd > out.log 2>&1: stdout을 파일로 바꾼 뒤 stderr도 같은 파일로 보내.cmd 2>&1 > out.log: stderr는 원래 stdout인 화면을 계속 가리키고 stdout만 파일로 바뀌어.
Bash 4 이상의 &> 단축형
cmd &> out.log는 두 스트림을 파일에 쓰고, cmd &>> out.log는 파일 뒤에 이어 써. POSIX sh에서는 지원하지 않으므로 이식성이 필요한 스크립트에는 > out.log 2>&1 형태를 사용해.
파일 디스크립터 복제를 왼쪽부터 따라가
2>&1 >file과 >file 2>&1의 최종 화면만 상상하지 말고 각 단계에서 1번과 2번이 어디를 가리키는지 적어 봐. 복제가 일어난 뒤에 stdout 목적지를 바꿔도 먼저 복제된 stderr의 목적지는 자동으로 따라가지 않아.
두 스트림을 합치면 정보가 사라져
사람이 읽는 빌드 로그에서는 stdout과 stderr를 한 파일에 모으는 편이 편할 수 있어. 하지만 다음 파서는 결과 데이터와 오류를 다시 나눌 수 없어. 누가 출력을 소비하는지 보고 합칠 시점을 정해.