> /dev/null 2>&1은 어떻게 작동하나요? [복사]

> /dev/null 2>&1은 어떻게 작동하나요? [복사]

> /dev/null출력을 리디렉션하면 화면에 인쇄되지 않는 이유 를 이해합니다 .

그러나 어떤 이유로 이것만으로는 항상 충분하지 않으며 여전히 무언가가 인쇄됩니다.

이러한 경우 > /dev/null 2>&1예상된 결과가 달성됩니다.

그러나 이것은 나를 약간 혼란스럽게 합니다. 누군가 이것이 어떻게 작동하는지 자세히 설명할 수 있습니까?

이 부분은 특히 혼란스럽습니다 &1. 그걸 보면 &'백그라운드에서 실행된다'는 생각이 든다. 1이 무슨 뜻인지는 모르겠지만, 2라면 어떨까요?

답변1

셸에서 실행되는 프로그램은 세 가지 스트림을 얻습니다.

0 - standard input [stdin]
1 - standard output [stdout]
2 - standard error (output) [stderr]

키보드 처럼 생각할 수 있습니다 stdin(단순화하여 파이프나 리디렉션이 없음).

그런 다음 화면에 무언가를 인쇄하기 위해 각 프로그램은 표준 출력 또는 표준 오류에 쓸 수 있습니다. 일반적으로 일반 출력은 으로 가고 stdout오류 출력은 로 이동합니다 stderr.

리디렉션하면 >표준 출력만 리디렉션됩니다. 당신이 사용할 수있는 1>.

리디렉션하면 2>stderr만 리디렉션됩니다.

따라서 프로그램이 무언가를 인쇄 stderr하고 다음을 수행하는 경우:

program > /dev/null

당신은 그것을 계속 볼 수 있습니다.

stderr출력을 보지 않으려면 리디렉션 stdout및 리디렉션이라는 두 가지 이상의 솔루션이 있습니다.stderr/dev/null

program > /dev/null 2>/dev/null

또는 귀하의 질문에 대한 답변은 다음과 같습니다. stderr로 리디렉션되며 l stdout로 리디렉션되었습니다./dev/nul

program > /dev/null 2>&1

이것이 Bash가 오른쪽에서 왼쪽 으로 2>&1읽는 것이므로 끝에 있습니다.stderrstdout

답변2

I/O 리디렉션의 복잡성을 이해하려면 시간이 좀 걸릴 것입니다. 주요 요점은 다음과 같습니다.

  1. 파일 설명자 번호 등은 , 0, 1m 등과 같은 2변수이거나 , , , ... 와 같은 배열에 대한 인덱스일 수 있습니다.xyzfd[0]fd[1]fd[2]
  2. 리디렉션 연산자 <, >, >><&>&이러한 변수에 값을 할당하는 연산자입니다.
  3. 이러한 할당은 명령줄에서 왼쪽에서 오른쪽으로 엄격하게 수행됩니다.앞으로명령은 명령줄에 나타나는 위치에 관계없이 실행됩니다.
  4. 파일 설명자 번호가 왼쪽에서 생략되면 기본값이 있거나 0최소한 처음 세 개의 연산자에 대한 값이 있습니다.1

이것만으로는 문제를 완전히 명확하게 설명할 수 없으므로 몇 가지 예를 들어 설명하겠습니다.


cmd arg arg arg. 여기에는 명시적인 리디렉션이 없지만 이 간단한 예는 셸이 작업을 수행하는 방법에 대한 기본 프로세스를 설정하는 데 도움이 됩니다. 그럼 여기서 무슨 일이 벌어지고 있는 걸까요?

  1. 셸은 새 프로세스를 분기하고 셸에서 코드를 계속 실행하며 결국 실행되지만 cmd아직은 실행되지 않습니다. 여기서부터 모든 것은 새로운 프로세스에서 발생합니다.
  2. 기본 I/O 리디렉션 설정: 이는 명시적 리디렉션과 거의 동일합니다 0</dev/tty 1>/dev/tty 2>/dev/tty.
  3. 이 과정에서 명령줄의 모든 명시적 리디렉션이 처리되어 이미 설정된 기본 할당이 수정될 수 있습니다.
  4. cmd arg arg arg설정된 파일 설명자 연결을 유지하면서 분기된 프로세스에서 실행됩니다 . (이는 exec다양한 시스템 호출을 통해 수행됩니다.)

그래서, 그래서 뭐 cmd arg arg arg >file?

  1. 새 프로세스를 포크하고 기본 파일 설명자 할당을 설정합니다.
  2. 첫 번째 명시적 리디렉션이 발견되었습니다 >file.
    • 동등하지만 드문 형태로 변환하십시오 1>file.
    • 출력을 열고 file파일 설명자에 추가합니다 1. 이는 이전에 (1)단계에서 수행된 stdout의 기본 할당을 재정의합니다.
  3. cmd arg arg arg동일한 프로세스에서 실행합니다. 파일 설명자가 1수정되어 stdout file이 터미널을 대체합니다.

하지만 이제는 많은 출력을 얻었고 이를 파일에 저장하는 대신 그냥 버리고 싶다고 가정해 보겠습니다. 글쎄요, 우리는 cmd arg arg arg>/dev/null

  • 이것은정확히/dev/null이 공급하려는 모든 바이트를 받아들인 다음 버리는 항상 존재하는 매직 파일이라는 점을 제외하면 위의 예와 모든 측면에서 동일합니다.

글쎄, 여전히 많은 출력이 나타납니다. 위의 리디렉션으로 문제가 해결되지 않는 이유는 무엇입니까? 특히 역사적으로 많은 UNIX 명령은 일반 출력과 오류 출력을 분리했습니다. 전자는 stdout(파일 설명자 1)으로 이동하고 후자는 stderr(파일 설명자 2)로 이동합니다. 이는 일반적으로 편리하지만, 맙소사, 출력이 사라지기를 원할 뿐입니다.

당신의 직업은 무엇입니까? 글쎄, 어떻게든 stderr로 전송된 모든 바이트를 /dev/null로 재할당(리디렉션)해야 합니다. 좋습니다. 다음이 작동합니다.

cmd arg arg arg >/dev/null 2>/dev/null

(이 질문은 처음에 요청한 질문이 아닙니다. 곧 나올 것입니다. 또한 이 양식을 참고하세요. /dev/null의 마법적인 속성으로 인해 원하는 작업만 수행됩니다.)

좋아요 여기서 무슨 일이 일어나고 있는 걸까요?

  1. 언제나 그렇듯이 새 프로세스를 포크하고 기본 파일 설명자 할당을 설정합니다.
  2. 첫 번째 명시적 리디렉션이 발견되었습니다 >/dev/null.
    • 동등하지만 드문 형태로 변환하십시오 1>/dev/null.
    • 출력을 열고 /dev/null파일 설명자에 추가합니다 1. 이는 이전에 (1)단계에서 수행된 stdout의 기본 할당을 재정의합니다.
  3. 다음 명시적 리디렉션'을 참조하세요 2>/dev/null.
    • 출력을 위해 열고 /dev/null열린 파일을 파일 설명자에 추가합니다 2. 이렇게 하면 설명자에 첨부된 원본 파일을 덮어쓰게 됩니다 2.
  4. cmd arg arg arg동일한 프로세스에서 실행합니다. 파일 설명자는 1기본 2설정에서 수정되었습니다.

두 개의 별도 개구부가 있다는 것을 인식하는 것이 중요합니다 /dev/null. 파일 설명자 12./dev/null을 일반 파일 이름으로 바꾸어 파일의 모든 출력을 캡처하려고 하면 문제가 발생할 수 있습니다.


마지막으로, 실제로 요청한 양식입니다.

cmd arg arg arg >/dev/null 2>&1

  1. 언제나 그렇듯이 새 프로세스를 포크하고 기본 파일 설명자 할당을 설정합니다.
  2. 첫 번째 명시적 리디렉션이 발견되었습니다 >/dev/null.
    • 동등하지만 드문 형태로 변환하십시오 1>/dev/null.
    • 출력을 열고 /dev/null파일 설명자에 추가합니다 1. 이는 이전에 (1)단계에서 수행된 stdout의 기본 할당을 재정의합니다.
  3. 다음 명시적 리디렉션'을 참조하세요 2>&1.
    • >&2현재 할당된 것과 동일한 열린 파일 에 대한 할당을 나타냅니다 1. 즉, y = x또는 과 같습니다 fd[2] = fd[1].
  4. cmd arg arg arg동일한 프로세스에서 실행합니다. 파일 설명자는 기본 설정에서 수정 1되었지만 이제 fd 1과 fd 2는 모두 다음을 가리킵니다.2동일한파일을 엽니다.

이 예에서는 이전 예와 같이 /dev/null을 두 번 열지 않고 한 번만 엽니다. /dev/null은 출력을 삭제하기 때문에 여기서의 차이점은 중요하지 않습니다.

그렇다면 언제가 중요합니까?


만세, 넌 이제 끝났어모두산출. 하지만 시간이 좀 지나면 화면에 보이는 순서대로 모든 출력을 파일에 담고 싶어질 것입니다.

내 이전 경고를 무시하고 믿을 수 없을 정도로 간단한 것부터 시작하세요.

cmd arg arg arg >file 2>file

이것은 이전에 설명한 대로 작동하지만, 내부를 살펴보면 filestout와 stderr이 이상하게 인터리브되어 있음을 알 수 있습니다. 아마도 stderr 비트가 파일 앞부분을 덮어쓰는 것처럼 보입니다. 젠장?

이 양식을 사용하면 양식을 file두 번 열 수 있습니다. 음, 어... 하지만 열려 있는 각 인스턴스 file에는 별도의 출력 위치가 있고 모두 0에서 시작합니다. 따라서 stdout이 미리 메가바이트의 출력을 생성하는 동안 stderr의 출력 위치는 0으로 유지되며 가끔 오류 메시지가 생성될 때만 앞으로 이동됩니다.


마지막으로 stderr 및 stdout을 단일 파일로 캡처하는 올바른 방법입니다.

cmd arg arg arg >file 2>&1

이는 다음 예와 정확히 동일한 설명입니다. 이전의 잘못된 형식과의 중요한 차이점은 stdout과 stderr이 모두 다음을 참조한다는 것입니다.동일한오픈 인스턴스 file공유하다출력 위치.

답변3

간단히 말해서:

  • > /dev/null표준 출력을 /dev/null인쇄하지 않고 으로 리디렉션하는 것을 의미합니다.
  • 2> &1stderr를 stdout으로 리디렉션합니다(로 리디렉션됨 /dev/null).

그러나 어떤 이유로 이것만으로는 항상 충분하지 않으며 여전히 무언가가 인쇄됩니다.

익숙하지 않은 경우를 대비해 다음 두 곳 중 하나로 물건을 보낼 수 있습니다.

  • 파일 설명자 1은 표준 출력입니다. 이는 애플리케이션이 콘텐츠를 출력할 때 일반적으로 사용하는 것입니다.
  • 파일 설명자 2는 stderr입니다. 이는 덜 일반적이지만 응용 프로그램은 일반적으로 오류가 발생할 때마다 stderr로 인쇄합니다.

대부분의 셸에서 stdout 및 stderr은 기본적으로 셸에 인쇄됩니다. 를 사용하면 > /dev/null표준 출력이 가상 싱크로 전달되므로 셸은 더 이상 표준 출력을 인쇄하지 않습니다. 그러나 stderr은 영향을 받지 않습니다. "어떤 이유로"라는 말은 응용 프로그램이 stderr에 쓴다는 것입니다.

관련 정보