리눅스 표준스트림과 리다이렉션

jhkim31·2024년 5월 10일

1. 파일 디스크립터

리눅스는 모든 자원(파일, 소켓, 장치등,…) 을 파일로 관리한다.

프로세스는 이러한 파일들에 파일 디스크립터라는 식별자로 접근하게 된다.

파일 디스크립터는 결국 파일을 나타내는 테이블의 인덱스이며 모든 프로세스는 자신만의 파일 디스크립터 테이블을 가지고 0, 1, 2는 표준 입력, 표준 출력, 표준 에러로 자동 할당 된다.

추가 : 동일한 파일이여도 프로세스마다 디스크립터가 다를 수 있고, 다른 파일 및 소켓이여도 프로세스마다 디스크립터가 같을 수 있다. 이유는 프로세스마다 디스크립터를 관리하기 때문

2. 표준 입력, 표준 출력, 표준 에러

프로세스가 가지는 파일디스크립터에 자동으로 할당되는 3개의 표준 스트림이 있다.

이는 해당 프로세스를 fork 해준 로부터 받아오게 되고, 각각 스트림은 다음과 같다.

  • 0 : 표준 입력 ⇒ 터미널 (키보드를 통한 입력)
  • 1 : 표준 출력 ⇒ 터미널 (모니터를 통한 출력)
  • 2 : 표준 에러 ⇒ 터미널 (모니터를 통한 에러 출력)

즉 기본적으로 표준입출력은 터미널로 지정되어 있어, 터미널로 입력을 받고 터미널로 결과와 에러를 출력하게 된다.

리다이렉션은 기존 터미널(이것도 결국 파일)이던 스트림 채널을 다른 파일로 변경하기 위함이다.

키보드와 모니터는 터미널을 통해 전달되기 때문에 키보드, 모니터 는 곧 터미널이라 봐도 무방하다.

이후 키보드, 모니터라는 말보다는 터미널이라는 말을 더 자주 사용한다.

커널, 셸, 터미널, tty, pty

3. 스트림 리다이렉션

리눅스는 리다이렉션을 통해 스트림의 방향을 제어할 수 있다.

  • 명령 > 파일 : 표준 출력, 에러를 파일로 변경한다. (덮어쓰기)
  • 명령 >> 파일 : 표준 출력, 에러를 파일로 변경한다. (추가)
  • 명령 < 파일 : 표준 입력을 파일로 변경한다.

셸에 입력하는 명령도 결국에는 프로세스고, 표준 스트림을 파일디스크립터로 가진다.

리다이렉션을 사용한다면 기존 터미널에서 출력되는 표준 출력, 표준 에러 를 다른 파일로 변경이 가능하다.

또한 터미널을 통해 입력되는 표준 입력또한 파일로 변경이 가능하다.

위에서 언급했듯 표준 출력의 디스크립터는 1, 표준 에러의 디스크립터는 2다.

고로 출력을 제어하기 위해선 1> 라고 사용해야 하고, 표준 에러를 제어하기 위해선 2> 라고 사용해야 한다.

여기서 표준 출력인 1은 생략이 가능해 > 로 사용할 수 있다.

또한 그 위의 디스크립터들도 사용이 가능하긴 하다 3>, 4>, 등…

3.1 리다이렉션 실습

>>> 는 파일을 덮어쓰냐, 추가로 쓰냐의 차이만 있기 때문에 >> 는 따로 언급하지 않는다.

3.1.1 표준 출력 리다이렉션

셸에서 ls 명령을 사용한다면 해당 디렉토리의 파일과 디렉토리를 확인할 수 있다.

명령의 결과가 표준 출력이기 때문에 터미널에 보여지게 된다.

이번에는 이러한 표준 출력d.txt라는 파일로 리다이렉션 시켜본다.

ls 명령의 결과는 터미널에 나오지 않고 리다이렉션된 d.txt라는 파일에 써진것을 알 수 있다.

3.1.3 표준 에러 리다이렉션

위에서는 표준 출력을 리다이렉션 시켜보았다.

표준 에러또한 동일하게 리다이렉션가 가능하다.

정의되지 않은 명령인 jh 를 실행시키면 에러가 발생한다.

이 에러를 d.txt 라는 파일에 리다이렉션 시키게 된다면

표준 출력 리다이렉션와 마찬가지로 터미널에 나오지 않고 d.txt라는 파일에 써진것을 알 수 있다.

그렇다면 jh 명령의 결과인 표준 에러> 를 사용하여 리다이렉션 시키면 어떻게 될까?

결과는 표준 에러터미널을 통해 출력되며, 아무것도 없는 표준 출력d.txt에 써지게 되어, d.txt에는 아무것도 써있지 않게 된다.

반대의 경우 (표준 출력을 2> 로 리다이렉션) 도 동일한 결과를 가진다.

3.1.4 표준 입력 리다이렉션

이번에는 표준 입력을 리다이렉션 시켜본다.

아래와 같은 파이썬 스크립트가 있다고 해보자.

# test.py

a = input()
print(a)

키보드로 입력을 받아 그 내용을 출력해주는 간단한 예시다.

위 스크립트를 실행시킬 쉘의 PID를 통해 파일 디스크립터를 확인해보자.

# 현재 쉘의 PID 확인
echo $$

# 특정 PID의 파일디스크립터 확인
ls -l /proc/{PID}/fd

표준 입(0)출(1)력, 에러(2) 모두 터미널을 가르키고 있는모습을 볼 수 있다.

때문에 터미널(키보드)을 통해 표준 입력을 하게 되면 표준 출력이 터미널을 통해 보여진다.


키보드로 입력, 모니터로 출력

여기서 input.txt 라는 파일을 만들어 표준 입력을 이 파일로 리다이렉션 시켜보자.


파일을 통한 표준 입력 리다이렉션

키보드를 통한 입력 말고, 파일을 통해 입력된 내용이 출력된것을 볼 수 있다.

3.1.5 리다이렉션을 사용한다면

리다이렉션을 사용한다면 이러한 것도 가능하다.

두개의 터미널을 연결하여 tty를 확인한다.

한 터미널의 명령 결과를 다른 터미널의 tty(파일)로 리다이렉트 한다.

이렇게 한다면 첫번째 터미널에서 실행한 명령을 두번째 터미널로 리다이렉트 시켜 결과가 두번째 터미널에 나오게 된다.

4. {명령어} > /dev/null 2>&1

디스크립터와 리다이렉션에 대해 공부하게된 이유다.

가끔씩 만나게 되는 코드인데 지금까지는 그냥 결과가 나오지 않게 하는건가보다 이해하고 있었다가, 자세하게 알아보고 싶어서 공부하게 되었다.

결론적으로 해당 리다이렉션은 표준 입출력을 널디바이스(/dev/null) 로 보내 버린다는 뜻이다.

그럼 하나씩 알아본다.

4.1 /dev/null

널디바이스, 블랙홀, 비트 버킷 등으로 불리는 널 장치에 대해 알아본다.

해당 장치에 쓰기 작업을 할경우 아무런 일도 일어나지 않지만, 쓰기에 대해서는 성공하게 된다.

한마디로 쓰레기통이다.

로그파일 같은 경우 파일 자체를 날려버릴순 없지만, 파일 내부의 내용을 지우고 싶을때 파일의 내용을 널 디바이스로 보내버려 파일은 내버려두고 내용만 지워버릴때 사용한다.

cat /dev/null > {내용만 지울 파일}

4.2 > /dev/null

결국 명령어의 결과를 널 디바이스 (쓰레기통) 으로 버려버린다는 것이다.

명령어의 결과를 확인하고 싶지 않을때 아예 명령의 결과를 널 디바이스로 보내버려 아무 결과도 나오지 않게 하는 것이다.

4.3 2>&1

위에서 표준 출력 스트림을 널 디바이스로 변경했다. 하지만 아직 표준 에러는 변경하지 않았기 때문에 에러의 경우는 터미널에 나오게 된다.

2>&1 은 표준 에러를 표준 출력과 동일한 장치로 리다이렉션 하겠다는 의미다. 고로

  • 명령어 > /dev/null 2> /dev/null
  • 명령어 > /dev/null 2>&1

은 동일한 의미인 것이다.

4.4 그래서 왜쓰는데

출력이 필요 없을때 쓴다.

6. Ref

표준입출력과 리다이렉션, 파이프에 대해서

What are some practical uses of STDIN redirection?

profile
김재현입니다.

0개의 댓글