Logo

쉘 리다이렉션(Redirection) 사용법

쉘 프로그래밍을 처음 하시는 분들이 스크립트를 읽으시다가 2>&1와 같은 알 수 없는 문법을 보고 당황하시는 경우가 있습니다. 이 것을 보통 리다이렉션(Redirection)이라고 하는데요. 어떤 명령의 입력이나 출력을 다른 곳으로 변경하기 위해서 사용됩니다.

이번 포스팅에서는 쉘 리다이렉션의 기본 사용법을 알아보고 다양한 예제를 통해 어떻게 실제 쉘 프로그래밍에 활용할 수 있는지 배워보겠습니다.

표준 스트림

쉘의 리다이렉션을 이해하려면 우선 MacOS와 같은 리눅스/유닉스 운영체제의 세 가지 표준 스트림(Standard Stream)을 알고 있어야 합니다

  • 표준 입력(Standard Input, stdin): 키보드로 입력을 받는 스트림입니다.
  • 표준 출력(Standard Output, stdout): 터미널에 정상 출력을 보내는 스트림입니다.
  • 표준 오류(Standard Error, stderr): 터미널에 오류 출력을 보내는 스트림입니다.

리다이렉션에서 표준 출력은 번호 1로 나타내고, 오류 출력은 번호 2로 나타내는데, 이 부분은 밑에서 더 설명을 드리겠습니다.

우리가 쉘에서 어떤 명령어를 실행하거나, 여러 명령어로 이루어진 쉡 스크립트를 실행하면, 각 명령이 정상적으로 처리되었든 오류가 발생하였든 터미널에 결과가 출력이 됩니다.

예를 들어, cat 명령어를 존재하는 파일을 상대로 실행하면 정상적으로 파일 내용이 터미널에 출력이 됩니다.

$ cat .gitignore
.idea
.DS_Store

그리고 존재하는 파일을 상대로 실행해도 오류 메시지가 터미널에 출력이 됩니다.

$ cat gitignore
cat: gitignore: No such file or directory

이렇게 터미널에서 일회성으로 명령어를 실행할 때는 이렇게 정상 출력과 오류 출력을 구분없이 터미널에 출력해도 크게 문제되지 않습니다. 하지만 쉘의 이러한 기본 처리 방식은 스크립트를 실행하거나 오랫동안 떠 있는 프로그램을 실행할 때는 적합하지 않죠.

일반적으로는 정상 출력과 오류 출력을 각각 별도의 파일에 저장해야 로그가 유실된 위험이 적고 디버깅이 용이할 것입니다.

출력 리다이렉션

> 연산자는 명령어의 출력 내용을 터미널에 보내지 않고 다른 곳으로 보낼 수 있도록 해줍니다. 가장 흔하게 볼 수 있는 사용 사례로 출력 내용을 로그 파일에 저장하는 것을 들 수 있습니다.

예를 들어, cat .gitignore 명령어의 실행 결과를 test.log 파일로 보내보겠습니다.

$ cat .gitignore > test.log

test.log의 내용을 터미널에 찍어보면 .gitignore 파일과 동일한 내용이 확인될 것입니다.

$ cat test.log
.idea
.DS_Store

> 연산자는 파일이 이미 존재하면 해당 파일을 덮어쓰기 때문에 주의가 필요합니다.

예를 들어, 제가 이번에는 cat README.md 실행 결과를 test.log 파일로 보내보겠습니다.

$ cat README.md > test.log

test.log 파일에 기존에 있던 .gitignore의 내용이 모두 사라지고, README.md 파일의 내용으로 완전히 대체가 된 것을 볼 수 있습니다.

$ cat test.log
# README
Please read me!

대신에 >> 연산자를 사용하면 기존 내용을 건들이지 않고 명령어 실행 결과를 파일 끝에 추가해줍니다.

$ cat .gitignore >> test.log

test.log 파일의 내용을 다시 확인해보면 README.md 파일의 내용이 .gitignore 파일에 덧붙여진 것을 볼 수 있습니다.

$ cat test.log
# README
Please read me!
.idea
.DS_Store

오류 리다이렉션

이번에는 존재하지 않는 파일을 대상으로 cat 명령어를 실행 후에 출력 결과를 test.log 파일로 보내보겠습니다.

😮 옷! 예상과 달리 오류 메시지가 그대로 터미널에 출력이 되는 것을 볼 수 있습니다.

$ cat gitignore > test.log
cat: gitignore: No such file or directory

test.log 파일은 내용이 비어 있네요.

$ cat test.log

왜 이런 일이 발생하는 걸까요? 🤔

비밀은 바로 맨 처음에 알려드린 표준 스트림을 나타내는 번호에 있습니다. >는 사실 1>의 축약된 형태이기 때문에, 정상 출력만 리다이렉션해줍니다. 그런데 우리는 오류 출력을 리다이렉션 하고 싶으므로 2>를 사용해야 합니다.

$ cat gitignore 2> test.log

이제 원했던 바와 같이 test.log 파일에 오류 내용이 저장되는 것을 볼 수 있습니다.

$ cat test.log
cat: gitignore: No such file or directory

어떤 사유로든 오류 출력을 아예 무시하고 싶다면 /dev/null 파일로 보내면 됩니다. /dev/null 파일은 어떤 출력을 보내도 그냥 무시해버리는 특수한 파일로 생각하시면 이해가 쉬우실 것 같습니다.

$ cat gitignore 2>/dev/null

2를 빼면 성공 출력까지 무시할 수 있겠죠?

$ cat gitignore >/dev/null

통합 리다이렉션

만약에 표준 출력과 오류 출력 모두를 리다이렉션 하고 싶다면 어떻게 해야할까요? 이럴 때는 숫자 1이나 2 대신에 & 기호를 사용하면 됩니다.

예를 들어, 존재하지 않는 파일을 상대로 cat 명령어를 실행하여 오류 내용을 다시 한 번 test.log 파일에 사용하여 덧붙여 보겠습니다. (>> 연산자 사용)

$ cat gitignore &>> test.log
$ cat test.log
cat: gitignore: No such file or directory
cat: gitignore: No such file or directory

이번에는 존재하는 파일 상대로 cat 명령어를 실행하여 파일 내용을 test.log 파일에 덧붙여 보겠습니다.

cat .gitignore &>> test.log
$ cat test.log
cat: gitignore: No such file or directory
cat: gitignore: No such file or directory
.idea
.DS_Store

정상 출력이든 오류 출력이든 가리지 않고 test.log 파일에 잘 추가되는 것을 볼 수 있습니다.

만약에 정상 출력은 success.log 파일로, 오류 출력은 error.log 파일로 보내고 싶다면 다음과 같은 형태로 명령어를 실행하시면 됩니다.

$ 명령어 > success.log 2> error.log

쉘 프로그래밍을 하다보면 오류 출력을 표준 출력으로 결합해야할 때가 있습니다. 보통 중요하지 않은 오류 때문에 프로그램의 실행이 멈추는 것을 방지할 수 있죠.

이럴 때는 다음과 같은 형태로 2>&1를 사용하여 오류 출력을 표준 출력으로 결합한 후에 파일로 리다이렉션하면 됩니다.

$ 명령어 > any.log 2>&1

입력 리다이렉션

< 연산자는 명령어의 입력 내용을 다른 곳으로 부터 가져올 수 있도록 해줍니다.

예를 들어, test.log 파일의 내용을 입력으로 cat 명령어를 실행해보겠습니다.

$ cat < test.log
cat: gitignore: No such file or directory
cat: gitignore: No such file or directory
.idea
.DS_Store

다른 예로, grep 명령여의 입력으로 test.log 파일의 내용을 보내보겠습니다.

$ grep "gitignore" < test.log
cat: gitignore: No such file or directory
cat: gitignore: No such file or directory

좀 응용을 해보자면… grep 명령어의 실행 결과를 터미널에 출력하는 대신에 파일에 저장할 수도 있겠죠? 😉

$ grep "gitignore" < test.log > grep.txt
$ cat grep.txt
cat: gitignore: No such file or directory
cat: gitignore: No such file or directory

마치면서

지금까지 쉘의 리다이렉션을 어떻게 사용하는지 다양한 예제를 통해서 살펴보았습니다. 리다이렉션이 얼마나 강력한지 느끼실 수 있는 기회가 되기를 바라며 본 포스팅이 여러분의 쉘 능력을 업그레이드하는데 도움이 되었으면 좋겠습니다1