리눅스 리디렉션이란? (feat. 톰캣 로그가 저장되는 원리)

리눅스를 쓰면 파일명.sh 형태의 bash 스크립트를 볼 일이 많습니다. 스크립트 내용을 살펴보면 자주 등장하는 기호들이 있는데 대표적인 것이 >, >>, 2>&1, 2> 등입니다. 이를 리디렉션이라고 부릅니다.

 

예를 들어, 아파치 톰캣을 실행하는 startup.sh 쉘 스크립트 파일에는 서버를 시작하고 출력되는 로그를 catalina.out 파일에 저장하는 내용이 있습니다.

...
CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out

exec "$PRGDIR"/"$EXECUTABLE" start \
    >> "$CATALINA_OUT" 2>&1 "&"
...

이 글을 읽으면 리디렉션이 사용된 위 스크립트를 이해하실 수 있습니다.

리디렉션이란?

리눅스에서 리디렉션(redirection)은 명령을 실행할 때 표준 입력과 출력 장치를 변경하는 기능입니다. 이 말을 이해하기 위해서는 리눅스의 표준 입력(stdin), 표준 출력(stdout), 표준 에러(stderr) 개념을 알아야 합니다. 간단히 설명드리겠습니다.

 

리눅스에서 모든 프로세스는 세 가지 스트림(Stream)이 있습니다.

  • 표준 입력(stdin) : 입력을 읽는 스트림입니다. 숫자 0으로 표기합니다.
  • 표준 출력(stdout) : 출력을 표시하는 스트림입니다. 숫자 1로 표기합니다.
  • 표준 에러(stderr) : 에러를 표시하는 스트림입니다. 숫자 2로 표기합니다.

예를 들어, 프롬프트에 ls를 치면 현재 위치에 있는 파일을 모두 정상 출력합니다. 이게 표준 출력(stdout)입니다. ls /asdf 처럼 존재하지 않는 경로를 대상으로 ls를 치면 리눅스는 명령이 잘못됐다고 에러를 뱉습니다. 이게 표준 에러(stderr)입니다.

 

리디렉션으로 뭘 할 수 있는지에 대한 예시를 보면 좀 더 이해가 되실 겁니다. 

 

예시) stdout 리디렉션

ls 명령어는 화면에 현재 위치의 파일들을 출력합니다. 그런데 이 출력 결과물을 리디렉션을 이용해서 파일에 저장할 수 있습니다.

ls > ls_result.txt

ls의 출력을 stdout으로 ls_result.txt라는 파일에 리디렉션 하는 명령입니다. 그 결과 ls_result.txt라는 파일이 생성되고 해당 파일에 출력 결과가 저장됩니다.

 

예시) stderr 리디렉션

이번엔 같은 방법으로 stderr를 리디렉션 해보겠습니다.

ls /asdf 2> ls_nonexistent_result.txt 

이번엔 >가 아닌 2>가 사용됐습니다. 그 이유는 리디렉션 기호 앞에는 스트림을 숫자로 표기하기 때문입니다. ls /asdf에 대한 출력은 stderr이기 때문에 2>를 사용해야 합니다. 첫 번째 예시처럼 아무 숫자를 표기하지 않고 쓰면 1번인 stdout으로 리디렉션 한다고 간주됩니다.

 

만약 위 예시에서 2> 대신 >를 쓰면 출력되는 stdout이 없기 때문에 ls_nonexistent_result.txt에 출력이 저장되지 않습니다.

 

예시) 추가모드 리디렉션

이미 생성된 파일에 리디렉션을 다시 하면 기존에 있는 내용이 덮어쓰기 됩니다. 그러지 않고 맨 아래부터 추가로 이어서 내용을 넣고 싶으면 > 대신 >>를 사용합니다.

ls >> ls_result.txt

 

예시) stdout과 stderr를 모두 리디렉션

같은 파일에 stdout과 stderr를 모두 리디렉션 하려면 아래와 같이 표기합니다.

ls /asdf > ls_result.txt 2>&1

맨 앞에 ls /asdf > ls_result.txt까지는 ls의 출력을 stdout으로 ls_result.txt에 리디렉션 한다는 의미입니다. 결과가 stderr이기 때문에 stdout으로 저장하면 저장되는 게 없을 겁니다. 그러나 뒤에 2>&1는 stderr를 stdout으로 리디렉션한다는 의미입니다.

 

위 명령 내용을 정리하면 이렇습니다.

1. ls 출력을 stdout으로 ls_result.txt에 리디렉트 해줘

2. 그런데 만약 결과가 stderr이면 stdout으로 리디렉션 해줘.

 

그 결과 ls_result.txt엔 stdout과 stderr 출력 모두 저장됩니다. 참고로 &는 구분자의 역할을 합니다. 표시한 1이 표준 스트림이라는 걸 인식시키기 위해 사용됩니다.

 

무슨 말인지는 알겠지만 다소 직관적이지 못한 쓰임으로 느껴집니다. 이런 수요를 반영해서인지 대신 사용할 수 있는 &>라는 표시도 있습니다. 

ls /asdf &> ls_result.txt

이 구문 역시 stdout과 stderr를 모두 ls_result.txt에 저장하라는 의미입니다. 좀 더 간단합니다. 

 

위 내용들이 헷갈리시면 굳이 이해하지 않으셔도 그냥 stdout과 stderr를 모두 저장하려고 할 때 이런 두 가지 방법이 있다고 생각하시면 됩니다. 

startup.sh 이해하기

이제 서두에 말씀드린 startup.sh의 일부 구문을 이해할 수 있습니다.

...
CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out

exec "$PRGDIR"/"$EXECUTABLE" start \
    >> "$CATALINA_OUT" 2>&1 "&"
...

1. CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out

로그 파일인 catalina.out 파일 경로를 CATALINA_OUT에 저장합니다.

 

2. exec "$PRGDIR"/"$EXECUTABLE" start \

톰캣 서버를 시작합니다.

 

3. >> "$CATALINA_OUT" 2>&1 "&"

그에 대한 stdout과 stderr 출력을 모두 catalina.out에 이어 쓰기 방식으로 리디렉션 합니다.

 

“&”는 백그라운드 실행을 한다는 표시입니다.

 

혹시 리눅스 표준 스트림에 대해 더 궁금하시면 아래의 글을 읽어주세요.

 

리눅스 stdin, stdout, stderr이란?

 

리눅스 stdin, stdout, stderr이란? (표준 스트림)

모든 리눅스 세 개의 표준 스트림이 존재합니다. 입력 스트림, 출력 스트림, 오류 출력 스트림입니다. 각각 stdin, stdout, stderr라고 부릅니다. 리눅스 표준 스트림 컴퓨터에서 스트림이란 데이터를

change-words.tistory.com

 

반응형

댓글

Designed by JB FACTORY