티스토리 뷰

2>&1은 stderr(표준 에러, 2번)를 stdout(표준 출력, 1번)이 현재 가는 곳으로 보내는 리다이렉션 문법이다.
이 문법이 필요한 이유는 정상 출력과 에러 출력이 처음부터 분리되어 있기 때문이다.
>가 stdout만 바꾸는 것과 달리, 2>&1은 stderr의 방향까지 맞춰 주기 때문에 로그 파일, 배치 작업, 백그라운드 실행에서 결과 차이가 생긴다.

핵심 요약

쉘의 출력은 하나처럼 보이지만 실제로는 둘이다.
stdout은 정상 결과이고, stderr는 오류 메시지다.
command > file 2>&1은 두 출력을 모두 파일로 보내지만, command 2>&1 > file은 순서 때문에 stderr가 터미널에 남는다.

왜 필요한가

터미널에서는 정상 출력과 에러 출력이 함께 보인다. 그래서 처음에는 둘이 같은 출력이라고 착각하기 쉽다. 하지만 파일로 저장하거나 다른 명령으로 넘기면 차이가 바로 드러난다. >는 stdout만 바꾸기 때문에, 사용자는 로그를 남겼다고 생각하지만 실제로는 정상 결과만 파일에 있고 에러는 화면에 남는 일이 생긴다.
문제는 이 상태가 운영 환경에서 바로 로그 누락으로 이어진다는 점이다. 배치 작업이 실패했는데 로그 파일에는 에러가 없고, 화면에서만 보였던 메시지는 이미 사라진다. 이런 한계를 해결하려면 stderr를 별도로 다루거나 stdout의 목적지에 맞춰줘야 한다. 그때 쓰는 문법이 2>&1이다.

예제

1. stdout만 파일로 보내기

echo "ok" > out.txt

결과는 out.txt에 ok가 기록된다. 이유는 >가 stdout만 파일로 보내기 때문이다. 정상 결과만 저장할 때는 충분하지만, 실패 원인까지 같이 남기려는 작업에는 부족하다.

2. stderr는 >로 저장되지 않는다

ls /not-exist > out.txt

결과는 에러 메시지가 터미널에 출력되고 out.txt에는 기대한 오류가 없다. 이유는 이 메시지가 stdout이 아니라 stderr이기 때문이다. 이 예제가 보여 주는 핵심은 “출력 전체를 파일로 보냈다”가 아니라 “stdout만 옮겼다”는 사실이다.

3. stderr만 따로 저장하기

ls /not-exist 2> err.txt

결과는 에러 메시지가 err.txt에 기록된다. 2>는 stderr 전용 리다이렉션이다. 정상 결과와 오류를 분리해 저장해야 하는 작업에서 이 방식이 필요하다.

4. stdout과 stderr를 함께 저장하기

sh -c 'echo ok; ls /not-exist' > all.log 2>&1

결과는 정상 출력과 에러 출력이 모두 all.log에 기록된다. 먼저 stdout이 파일로 바뀌고, 그다음 stderr가 stdout의 현재 목적지를 따라가기 때문이다. 그래서 2>&1은 “같은 파일 이름을 다시 지정한다”보다 “stdout의 방향을 따라붙는다”로 이해하는 편이 정확하다.

5. 순서를 바꾸면 결과가 달라진다

sh -c 'echo ok; ls /not-exist' 2>&1 > all.log

이 경우 ok는 파일에 기록되지만 에러 메시지는 터미널에 남는다. 이유는 쉘이 왼쪽부터 처리하기 때문이다. 2>&1이 먼저 실행될 때 stdout은 아직 터미널을 가리키고 있으므로 stderr도 터미널에 묶인다. 그다음 stdout만 파일로 바뀐다.

실무 적용

백그라운드 실행에서는 다음 패턴이 자주 나온다.

nohup python app.py > app.log 2>&1 &

이 구조는 프로세스를 터미널과 분리하면서 stdout과 stderr를 한 파일에 남긴다. 장애가 나도 로그 파일 하나로 실행 흐름과 오류를 함께 확인할 수 있다.
크론이나 배치 작업도 비슷하다.

job.sh > job.log 2>&1

이렇게 하면 정상 로그와 오류 로그가 한곳에 모여서 실패 시점의 문맥을 같이 읽을 수 있다. 반대로 결과가 아예 필요 없는 작업은 /dev/null로 버린다.

command > /dev/null 2>&1

다만 이 방식은 로그를 완전히 지우기 때문에 원인 분석이 필요한 작업에는 맞지 않는다.

흔한 실수

첫 번째 실수는 순서를 바꾸는 것이다.

command 2>&1 > out.log

이 경우 stderr는 터미널에 남는다. 올바른 형태는 command > out.log 2>&1이다.
두 번째 실수는 >만 쓰고 전체 로그가 저장됐다고 생각하는 것이다. >는 stdout만 바꾼다. 오류까지 필요하면 2>&1을 추가해야 한다.
세 번째 실수는 모든 상황에서 무조건 합치는 것이다. 자동화 작업에서는 정상 데이터와 오류를 분리해야 할 때가 있다. 예를 들어 결과 파일은 stdout으로, 실패 원인은 stderr로 나누는 편이 후처리에 더 안전하다.

정리

2>&1은 stderr를 stdout의 현재 목적지로 보내는 문법이다.
>는 stdout만 바꾸므로 에러까지 한곳에 남기려면 2>&1이 필요하다.
그리고 이 문법은 순서에 따라 결과가 달라지므로 > file 2>&1 형태로 이해해야 한다.
핵심은 기호를 외우는 것이 아니라 stdout과 stderr가 원래 분리된 흐름이라는 사실을 이해하는 데 있다.