...
리눅스 리다이렉션
2>&1 는 표준에러를 표준출력으로 redirection 하라는 의미이다.
보통 프로그램에서 에러가 발생하면, 화면에 에러메세지를 표시해서 사용자에게 경고를 주게 된다. 이러한 기본적인 에러 동작에 대해 사용자가 임의로 재지정하여, 오류가 발생해도 경고메세지 출력을 내 마음대로 조정 할 수 있는데 이것을 표준 에러 리다이렉션이라고 한다.
다시 돌아가서 2>&1 이라함은 에러가 발생하면 프로그램이 작동을 멈추거나 꺼지지않게 하고, 대신 에러내용을 표준 출력 동작으로 행동하게 하여 프로그램은 오류가 있더라도 화면에 경고메세지를 출력하지 말고 파일이나 딴 곳으로 처리하고, 어쨋든 계속 실행하라는 의미로 볼 수 있다.
이정도면, 2>&1 가 의미하는 바는 알았지만, 보다 머릿속에 정확히 기억이 되도록 기호의 의미까지 하나하나 파헤쳐 보고 명령어 사용처 예제 까지 소개해 보겠다.
리다이렉션 기호 조합 정리
리다이렉션 (입출력 재지정)
복습 차원에서 설명하자면,
리다이렉션(입출력 재지정)이란 일반적인 키보드 입력, 화면 출력을 사용하지 않고 사용자 마음대로 입력, 출력을 재지정 하겠다는 말이다.
본래 표준입력은 기본적으로 키보드에서 직접 받아오고, 표준 출력은 기본적으로 따로 디스크에 저장하지 않고 화면에 출력된다.
이러한 기본적인 하드웨어적인 입출력 동작을 변경한다는 것이다.
대표적으로 키보드에서 입력을 받지않고 파일내용을 입력으로 받거나, 내용을 화면에 출력하지않고 파일에 저장하는 것이 있다.
리다이렉션 기호 | 방향 | 의미 |
> | 표준 출력 | 명령 > 파일 : 명령의 결과를 파일로 저장 |
>> | 표준 출력(추가) | 명령 >> 파일 : 명령의 결과를 기존 파일 데이터에 추가 |
< | 표준 입력 | 명령 < 파일 : 파일의 데이터를 명령에 입력 |
리다이렉션에 대해서 따로 자세하게 포스팅 해둔 것이 있다.
파일 디스크립터
표준 입력과 표준 출력 그리고 표준 에러를 쉘이나 시스템 프로그래밍에서는 숫자로도 표현할 수 있는데 이를 파일 디스크립터라고 한다.
유닉스 시스템은 일반적인 파일부터 디렉토리, 소켓, 파이프, 블록/캐릭터 디바이스 등등 모든 객체들을 파일로 관리하는데, 쉘은 작업중 필요한 파일에 일련번호를 붙여서 관리한다.
이 일련번호가 파일 디스크립터며, 표준 입출력 장치도 이 일련번호로 제어된다.
그래서 사용자는 이 일련번호를 이용하여 입출력 장치를 변경(리다이렉션) 할수 있는 것이다.
파일디스크립터(일련번호) | 이름 | 용도 | 표준장치 |
0 | stdin | 명령어에 입력될 내용을 저장 | 키보드 |
1 | stdout | 명령어에서 출력될 내용을 저장 | 화면 |
2 | stderr | 명령어에서 출력될 에러메시지를 저장 | 화면 |
다양한 리다이렉션 기호 조합
위에서 배운 리다이렉션 꺾쇠 기호와 파일디스크립터 일련번호 그리고 & 와 ! 를 이용하여 다양한 리다이렉션 조합이 가능하다.
$ 명령 >& 파일명 # : 명령이 실행된 표준 출력의 결과와 에러를 파일로 출력
$ 명령 >>& 파일명 # : 명령이 실행된 표준 출력의 결과와 에러를 파일로 덧붙여 출력
$ 명령 >! 파일명 # : 파일의 존재 유무와 상관없이 생성하고 명령이 실행된 표준 출력의 결과를 파일로 출력
$ 명령 >>! 파일명 # : 파일의 존재 유무와 상관없이 생성하고 파일에 덧붙여 출력
$ 명령 >&! 파일명 # : 파일의 존재 유무와 상관없이 생성하고 명령이 실행된 표준 출력의 결과와 에러를 파일로 출력
$ 명령 >>&! 파일명 # : 파일의 존재 유무와 상관없이 생성하고 명령이 실행된 표준 출력의 결과와 에러를 파일에 덧붙여 출력
$ 명령 1> 파일명 # : 일련번호 1쓰나 안쓰나 어쨋든 출력을 의미하기에 '명령 > 파일명' 와 같다.
$ 명령 2> err.txt # : 만일 명령을 실행하다 에러가 나면, 에러를 화면에 출력하지 말고 파일에 기록하도록 재지정
$ 명령 2>> err.txt # : 오류가 나면 에러내용을 계속 파일에 덧붙여 추가한다.
$ 명령 2>&1 파일명 # : 표준에러를 표준출력 동작으로 재지정 하라는 뜻
>| # : 출력을 리다이렉션 할 때 NOCLOBBER 설정을 무시한다
<> filename # : 장치 파일(/dev)이면, 표준 출력, 표준 입력 등에 모두 사용한다.
2>&1 완벽 이해하기
표준에러를 표준출력 동작으로 재지정 하라는 말은 알겠다.
하지만 어떤식으로 실무에서 사용되는지 아직도 모호하다.
다음 명령어 예제로 한방에 정리해본다.
$ ls > log.txt # ls 명령어 결과를 화면에 출력하는 표준 출력 동작을 재지정해 log.txt에 출력 즉, 저장하도록 한다.
정상적으로 디렉토리 리스트 내용이 파일에 잘 들어가있음을 확인 할 수 있다.
그럼 만일 명령어가 에러나면 어떻게 될까?
-ERR 라는 리눅스에 존재하지 않는 옵션을 줘서 일부러 에러를 내보게 해보겠다.
$ ls -ERR > log.txt # 명령어가 에러나면 어떻게 될까? 파일에 저장될까?
이상한 명령어를 실행했으니 당연하게도 오류메세지가 화면에 출력되어 사용자에게 경고를 준다.
한번 log.txt 파일을 조회해봤더니 내용이 아무것도 안들어 가 있다.
그럼 만일 명령어가 에러가 뜨면 화면에 오류메세지를 출력하는게 아니라, 에러를 아예 파일에 저장하게 해서 매끄럽게 진행하고 싶다면 어떻게 할까?
$ ls -ERR 2> log.txt # 표준오류 재지정을 통해 에러가 날경우 화면에 오류난다고 표시하지말고 그냥 파일에 저장한다.
log.txt 파일안에 오류 메세지가 들어있다.
만일 프로그램이 에러가 나도 막 화면에 에러난다고 난리치는게 아니라 조용히 로그에 기록되어서 사용성이 좋아졌다.
그럼 이대로 하면 매끄러운 프로그램이 완성되었을까?
한번 정상적인 명령어로 바꿔서 그대로 실행해보자.
$ ls 2> log.txt
위에선 정상적으로 디렉토리 리스트 내용들이 파일안에 들어가 있었는데, 조회해보니 아무것도 안들어가 있다.
사진을 보면 그대로 화면에 출력 되어버린다.
이것이 표준 출력 과 표준 에러의 차이 이다.
- 표준 출력은 정상적인 명령어의 결과 내용의 출력을 화면에서 파일로 바꾼것 뿐이고,
- 표준 에러는 오류메세지 출력을 화면에서 파일로 바꾼 것 뿐이다.
따라서, 2> 표준 에러 재지정은 오류메세지만 취급하기 때문에 정상적인 명령에 대해서 아무런 작업을 하지 않는 것이다.
그러면 명령어가 성공해도 파일에 내용을 넣고, 실패해도 파일에 내용을 한꺼번에 기록하고 싶다면 어떻게 할까?
$ ls >2> log.txt # 이런 명령어는 없다 -_-;
$ ls > log.txt 2> log.txt
# 만일 명령어를 실행해서 성공하면 표준 출력 재지정을 통해 파일에 기록하고
# 명령어가 실패하면 표준 에러 재지정을 통해 파일에 기록하도록 조정
사진에서 보듯이, 명령어가 성공하면 결과 내용이 파일에 기록되었고,
명령어가 실패하면 오류메세지가 파일에 기록됨을 확인 할 수 있다.
명령어가 성공하든 실패하든 둘다 파일에 기록되도록 설정에 성공한 것이다!!
그리고 2>&1 는 위의 명령어를 함축한 버젼이라 보면 된다! (명령어가 너무 길잖아?)
$ ls > log.txt 2>&1
윗 명령어를 기호 하나하나 자세히 정리하자면 이렇게 된다. (이것으로 완벽하게 이해하고 완벽히 암기가 됬음을 바란다.)
2>&1 는 crontab에서도 요긴하게 쓰일 수 있다.
만일 표준 에러를 재지정 하지않으면, 어떤 다른 계정의 사용자가 리눅스를 이용하다 cron에 의해 에러가 나는 스크립트가 실행되서 갑자기 허구한날에 터미널에 왠 쌩뚱맞은 오류 메세지가 떠버리는 불상사가 생길 수 있기 때문이다.
/dev/null 이해하기
이런 명령어를 접해봤을 것이다.
$ /script.sh > /dev/null 2>&1
왠 쌩뚱맞은 문법이라 처음에는 겁 먹었겠지만 이제는 그럴 필요가 없다.
/dev/null 는 블랙홀 이라고 이해하면 된다.
이 경로에 보내지는 모든 파일과 데이터들은 블랙홀에 빨려들어가서 無가 된다.
즉, /dev/null로 결과를 보낸다는 것은,
데이터를 죄다 말끔히 없애버려서 깔끔하게 화면에 표시하지 않는다는 것을 말한다.
따라서 특정 명령어를 실행한 후에 출력이 필요 없는 경우엔 > /dev/null 로 리다이렉션을 하면 된다.
그리고 > /dev/null 2>&1 의미는 스크립트의 출력 결과도 에러 내용도 /dev/null에 리다이렉션 시켜서 버려버린다는 뜻을 의미한다.
# 참고자료
https://blog.naver.com/dev_zion/222631283389
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.