리다이렉션
stdout
프로세스를 실행하면서 로그 경로를 지정할 때 아래와 같은 명령어를 종종 사용한다.
command > out.log 2>&1 이 명령어의 의미는 아래와 같다:
stdout은 out.log로 보내고,
stderr도 stdout이 가리키는 곳, 즉 out.log로 보내라 command > out.log 부분을 조금 뜯어서 보면:
command > out.log stdout을 out.log 파일로 보내라는 의미이고, 이는 보다 명시적으로 아래와 같이 작성할 수 있다.
command 1> out.log 결국 > 은 1> 와 같다고 볼 수 있다.
stderr
위 명령어를 실행하다가 에러가 발생하는 경우, 에러는 out.log로 가지 않고 터미널에 출력된다. stderr에 대한 경로를 별도로 작성하지 않았기 때문이다.
command 1> out.log 2> error.log 위와 같이 작성하면 stdout은 out.log 로, stderr는 error.log 로 보낸다는 뜻이다.
위 명령어를 축약하면 아래와 같이 작성할 수 있다.
command > app.log 2>&1 stdout을 app.log로 보내고, 2(stderr)는 1(stdout)으로 보낸다. 결국 stdout과 stderr을 보두 app.log로 보낸다는 뜻이다. 하나씩 뜯어보면 아래와 같이 정리할 수 있다.
참고로 > 는 기본적으로 “덮어쓰기”로 동작한다. 파일을 대상으로 하는 경우 해당 파일의 모든 내용이 날아가고 새롭게 작성된다. >> 는 기존 내용 뒤에 이어서 작성한다.
프로그램이 실행되면 기본적으로 3개의 fd가 열린다:
fd란 File Descriptor의 줄임말이고 프로세스가 파일, 터미널, 파이프, 소켓 등을 다룰 때 사용하는 번호표이다. 만약 command 2>1 와 같이 사용한다면 stderr는 1 이라는 파일이 생성되면서 그곳에 쓰여질 것이다.
다시 돌아와서, > 은 리다이렉션이라고 했다. 그리고 > 와 1> 은 같은 말이다. 그럼 아래 명령어를 실행하면 어떻게 될까?
command 2>&1 > out.log -
2(stderr)를 fd 1이 가리키는 곳(터미널)로 보내고 : 에러가 터미널에 출력된다.
-
1>리다이렉션에 의해 stdout을 out.log로 보낸다
리다이렉션은 왼쪽부터 순차적으로 처리되기 때문에 fd 1이 아직 터미널을 가리키고 있는 상황에서 2>&1로 보내는 것은 의도대로 동작하지 않는다.
출력 버리기
/dev/null 은 리눅스의 특수파일이다. 여기에 기록한 내용은 전부 버려진다. 따라서 stdout을 버리고 싶다면 아래와 같이 쓸 수 있다.
command > /dev/null stderr를 버리고 싶다면? 아래와 같이 쓴다.
command 2> /dev/null 둘 다 버리고 싶다면 위에서 설명한 방식을 응용하여 아래와 같이 쓸 수 있다.
command > /dev/null 2>&1 파이프(|)와 같이 쓰는 경우
파이프를 사용하면 stdout만 다음 명령어로 넘겨지기 때문에 아래와 같은 명령어에서는 에러 출력의 “error” 키워드를 잡을 수 없다.
command | grep error 이 때는 stderr를 fd 1(stdout)으로 보내고 파이프로 넘기면 된다.
command 2>&1 | grep error 대표 패턴
백그라운드에서 서버를 띄울 때 아래 패턴을 많이 쓴다.
nohup ./app >> app.log 2>&1 & 모든 출력을 app.log에 저장하고 백그라운드로 실행하며 기존 app.log에 이어쓰기 함