리눅스 명령어를 보면, 2>&1도 많이 쓰고, 2>&1과 tee를 같이 쓰는 것도 많이 보았을 것이에요. 이것이 어떤 의미인지 정확하게 이해해 보도록 합시다.
명령어 > 1.txt
먼저 echo 1 > 1.txt는 알다시피, echo 1의 결과를 파일 1.txt에 쓰는 명령어입니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi8.png)
위 명령어는 무엇을 의미할까요?
- 프로그램 1의 출력을
- stdout이 아닌, 1.txt에 하게 한다.
는 의미입니다. 그러면 실제 프로그램 1의 fd에는 어떤 값들이 저장 되어 있을까요?
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi9.png)
0은 /dev/pts/0, 2도 /dev/pts/0인 것을 알 수 있어요. 문제는, 1인데, 1이 /home/cho/test/1.txt로 바뀌었음을 알 수 있어요. 즉, redirect 명령을 통해서 무엇을 할 수 있다는 이야기인가요?
- 특정 file descriptor의 정보를
- 다른 정보로 바꿀 수 있다.
는 것입니다. 특정 fd의 정보를 다른 정보로 바꾸었다. 위 예제에서는 1번 파일 디스크립터가 1.txt에 연결되어 있다는 정보로 바꾼 것입니다. 결국 본질은, 특정 fd의 정보를 redirection 으로 바꾸었다는 것입니다.
리눅스 2>&1
그러면, n>&m은 무엇일까요? 둘 다 정수인 경우
- 파일 디스크립터 n에 대한 정보가
- 파일 디스크립터 m에 대한 정보로 쓰여진다.
입니다. 즉, 리눅스 2>&1 명령어는, 파일 디스크립터 2번이, 파일 디스크립터 1번에 대한 정보로 쓰여진다가 되겠습니다. duplicate로 생각하시면 됩니다. 그러면, 이것도 예제를 보도록 합시다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi1.png)
1번 명령어는 무엇을 의미할까요? left to right 법칙으로 해석해 봅시다.
- 프로그램 1의 stdout을 /dev/null로 바꾸어요.
- 디스크립터 2번에 대한 정보를 디스크립터 1에 대한 정보로 바꾸어요.
step by step으로 봅시다. 먼저 /dev/null로 출력을 redirect 시켰습니다. 이 경우, fd 정보가 아래와 같이 바뀝니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi11-1.png)
1번 데스크립터가 원래는 pts/0 (터미널)을 가리키고 있었습니다. 그런데, redirect 때문에, /dev/null 로 바뀌었다는 것이 포인트입니다. 다음 2>&1에 의해, 2번 데스크립터에 대한 정보가, 1번 데스크립터에 대한 정보로 바뀌게 됩니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi12-1.png)
따라서 2번은, /dev/null을 가리키게 됩니다. dup2를 아신다면 이해가 편하겠네요.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi2.png)
실행 결과는 위와 같습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi3.png)
그러면 이 명령어는 어떨까요? 이 경우
- 디스크립터 2번에 대한 정보를, 디스크립터 1번에 대한 정보로 바꿉니다.
- 그리고 /dev/null 로 표준 출력을 redirect 합니다.
이것도 step by step으로 이해해 보겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/nn2.png)
먼저, 0, 1, 2가 같은 터미널을 가리키고 있어요. 이 상황에서 2번에 대한 정보를, 1번에 대한 정보로 바꾼다고 한다면 위 그림과 같이 그려집니다. 다음에, 표준 출력을 /dev/null로 리다이렉트 합니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/nn1.png)
이 경우, 요래 상황이 그려집니다. 1번 명령어와는 상황이 다르다는 것을 주의해야 합니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi4.png)
실제로 1번 프로그램의 파일 디스크립터를 보면, 위와 같게 나옵니다. 이 차이를 아셨다면, tee에 대해서 보도록 하겠습니다.
tee 명령어와 pipe
아래 명령어를 보겠습니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi15.png)
cat 4 2>&1 command의 결과를 받아, tee의 input으로 쓰고 있어요. 이 command 전체를 괄호로 묶었음을 알 수 있어요. 여기서 tee는 표준 입력을 받아, stdout과 파일로 출력합니다. 그리고, 보통 piping과 같이 쓰이는 경우가 매우 흔합니다. 위 명령어는 아래를 의미합니다.
- command를 실행한 결과를
- tee로 받고, 이를 stdout과 파일로 출력합니다.
먼저, 4는 디렉토리입니다. 만약에 cat 4를 하면 디렉토리라는 에러가 뜰 겁니다. 뒤에 2>&1이 붙었기 때문에, cat 4 2>&1은 아래와 같이 상황이 도식화 될 겁니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi16.png)
따라서, 에러 메세지도, stdout으로 나가게 됩니다. 이것을 tee 프로세스의 input이 밭게 됩니다. 다음에 piping으로 인해, cat과 tee는 아래 그림과 같이 도식화 됩니다.
![](https://codingdog.pe.kr/wp-content/uploads/2023/09/redi17.png)
입력 받은 것을 stdout과 file에 출력하게 되므로, mkdir 4가 실패되었다는 내용이 1.txt 파일과 터미널에 출력되게 됩니다.
내용 잘 읽었습니다. 그림과 함께 찬찬히 설명되어서 좋네요!
참고로 2>&1 > /dev/null 의 그림이 std1과 std2가 사로 바뀐 것 같습니다. 그림6 앞에 도식이요.
아. 6 앞에 도식 수정하였습니다.. 감사합니다.