쉘 리다이렉션(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