[bash] 쉘에서 “2> & 1″은 무엇을 의미합니까?

유닉스 쉘에서 추가 조작 을 위해 스트림 으로 결합 stderr하고 싶다면 명령 끝에 다음을 추가 할 수 있습니다.stdoutstdout

2>&1

따라서 head의 출력에서 사용하려면 g++다음과 같이 할 수 있습니다.

g++ lots_of_errors 2>&1 | head

처음 몇 개의 오류 만 볼 수 있습니다.

나는 항상 이것을 기억하는 데 어려움을 겪고 있으며 끊임없이 찾아야하며, 주로이 특정 트릭의 구문을 완전히 이해하지 못하기 때문입니다.

누군가 이것을 분해하여 성격별로 설명 할 수 있습니까 2>&1 ?



답변

파일 디스크립터 1은 표준 출력 ( stdout)입니다.
파일 디스크립터 2는 표준 오류 ( stderr)입니다.

첫째,에 : 여기에 (이 완전히 정확하지 않지만)이 구문을 기억하는 한 방법입니다 2>1리디렉션 할 수있는 좋은 방법처럼 보일 수 있습니다 stderr에가 stdout. 그러나 실제로는 ” stderr이름이 지정된 파일로 리디렉션”으로 해석됩니다 1. &다음은 파일 설명자가 아니라 파일 설명 자임을 나타냅니다. 따라서 구문은 다음과 같습니다 2>&1.


답변

echo test > afile.txt

stdout을로 리디렉션합니다 afile.txt. 이것은하는 것과 같습니다

echo test 1> afile.txt

stderr을 리디렉션하려면 다음을 수행하십시오.

echo test 2> afile.txt

>& 스트림을 다른 파일 설명 자로 리디렉션하는 구문입니다. 0은 stdin, 1은 stdout, 2는 stderr입니다.

다음을 수행하여 stdout을 stderr로 리디렉션 할 수 있습니다.

echo test 1>&2 # or echo test >&2

혹은 그 반대로도:

echo test 2>&1

즉, 2>stderr을 (지정되지 않은) 파일로 &1리디렉션하고 stderr을 stdout에 리디렉션합니다.


답변

리디렉션에 대한 몇 가지 요령

이것에 대한 일부 구문 특수성은 중요한 동작을 가질 수 있습니다. 리디렉션에 대한 몇 가지 작은 샘플이 STDERR, STDOUT그리고 인수 순서 .

1-덮어 쓰기 또는 추가?

기호 >의미 리디렉션 .

  • >전체 완성 된 파일로 전송 , 대상이있는 경우 덮어 쓰기 의미 합니다 ( 나중에 # 3의noclobber bash 기능 참조 ).
  • >>존재하는 경우 대상 에 추가하는외에도 보내기를 의미 합니다.

어쨌든 파일이 없으면 작성됩니다.

2- 쉘 명령 행 은 순서에 따라 다릅니다 !!

이를 테스트하기 위해 두 가지 출력 모두에 무언가를 보내는 간단한 명령이 필요 합니다 .

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

( /tnt물론; 이라는 이름의 디렉토리가 없을 것으로 예상합니다 .) 글쎄, 우리는 그것을 가지고있다 !!

자, 보자 :

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

마지막 명령 줄 STDERR은 콘솔에 덤프 되며 예상되는 동작이 아닌 것 같습니다 … 그러나 …

한 출력, 다른 출력 또는 둘 다에 대해 일부 포스트 필터링 을 수행하려는 경우 :

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

이 문단의 마지막 명령 행은 이전 문단과 똑같습니다. 여기에서 필자 가 예상 한 동작이 아닌 것 같습니다 (따라서 이것은 예상 된 동작 일 수도 있습니다).

글쎄, 두 출력에서 ​​다른 작업수행 하기 위해 리디렉션에 대한 약간의 트릭이 있습니다
.

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

참고 : &9디스크립터는로 인해 자연스럽게 발생합니다 ) 9>&2.

부록 : nota! 새로운 버전으로( >4.0) 이런 종류의 작업을 수행하기위한 새로운 기능과 더 섹시한 구문이 있습니다.

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

마지막으로 이러한 계단식 출력 형식의 경우 :

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

부록 : nota! 두 가지 방식으로 동일한 새 구문 :

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

경우 STDOUT, 특정 필터를 통해 이동 STDERR다른 그리고 마지막으로 모두 출력은 세 번째 명령 필터를 통해 이동을 합병했다.

3- noclobber옵션과 >|구문 에 관한 단어

덮어 쓰기 에 관한 것입니다 .

set -o noclobberbash가 기존 파일을 덮어 쓰지 않도록 지시 하지만 >|구문을 사용하면 다음 과 같은 제한 사항을 통과 할 수 있습니다.

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

매번 파일을 덮어 씁니다.

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

로 통과 >|:

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

이 옵션을 설정 해제하거나 이미 설정했는지 문의하십시오.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4-마지막 트릭 등 …

주어진 명령의 출력을 리디렉션하기 위해 올바른 구문은 다음과 같습니다.

$ ls -ld /tmp /tnt >/dev/null 2>&1

특별한 경우에는 다음과 같은 바로 가기 구문이 있습니다. &>… 또는>&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

참고 : 2>&1존재 1>&2하는 경우 올바른 구문이기도합니다.

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b- 이제 다음에 대해 생각해 보도록하겠습니다.

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c- 더 많은 정보에 관심이 있다면

다음을 누르면 훌륭한 매뉴얼을 읽을 수 있습니다.

man -Len -Pless\ +/^REDIRECTION bash

안에 콘솔 😉


답변

나는 리디렉션에이 화려한 게시물을 발견 : 모든 재 지정에 대해

표준 출력 및 표준 오류를 파일로 리디렉션

$ 명령 &> 파일

이 단일 라이너는 &>연산자를 사용하여 출력 스트림 (stdout 및 stderr)을 명령에서 파일로 리디렉션합니다. 두 스트림을 동일한 대상으로 빠르게 리디렉션하기위한 Bash의 바로 가기입니다.

Bash가 두 스트림을 리디렉션 한 후 파일 디스크립터 테이블의 모습은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

보시다시피 stdout과 stderr은 이제를 가리 킵니다 file. 따라서 stdout 및 stderr에 작성된 내용은으로 기록됩니다 file.

두 스트림을 동일한 대상으로 리디렉션하는 방법에는 여러 가지가 있습니다. 각 스트림을 차례로 리디렉션 할 수 있습니다.

$ 명령> 파일 2> & 1

이것은 두 스트림을 파일로 리디렉션하는 훨씬 일반적인 방법입니다. 첫 번째 stdout이 파일로 경로 재 지정된 후 stderr이 stdout과 동일하도록 복제됩니다. 따라서 두 스트림이 모두를 가리 킵니다 file.

Bash가 여러 리디렉션을 발견하면 왼쪽에서 오른쪽으로 처리합니다. 단계를 수행하고 어떻게 발생하는지 봅시다. 명령을 실행하기 전에 Bash의 파일 디스크립터 테이블은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

이제 Bash는 첫 번째 리디렉션 파일을 처리합니다. 우리는 이것을 전에 보았고 stdout이 파일을 가리 키도록합니다.

여기에 이미지 설명을 입력하십시오

다음 Bash는 두 번째 리디렉션 2> & 1을 봅니다. 우리는 이전에이 리디렉션을 보지 못했습니다. 이것은 파일 디스크립터 2를 파일 디스크립터 1의 사본으로 복제하여 다음을 얻습니다.

여기에 이미지 설명을 입력하십시오

두 스트림 모두 파일로 리디렉션되었습니다.

그러나 여기서 조심하십시오! 쓰기

명령> 파일 2> & 1

쓰기와 동일하지 않습니다 :

$ 명령 2> & 1> 파일

Bash에서 리디렉션 순서가 중요합니다! 이 명령은 표준 출력 만 파일로 리디렉션합니다. stderr는 여전히 터미널에 인쇄됩니다. 그 이유를 이해하려면 단계를 다시 수행하십시오. 따라서 명령을 실행하기 전에 파일 디스크립터 테이블은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

이제 Bash는 리디렉션을 왼쪽에서 오른쪽으로 처리합니다. 먼저 2> & 1을보고 stderr을 stdout에 복제합니다. 파일 디스크립터 테이블은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

이제 Bash는 두 번째 경로 재 지정을보고 >filestdout을 파일로 경로 재 지정합니다.

여기에 이미지 설명을 입력하십시오

여기서 무슨 일이 일어나는지 보십니까? Stdout은 이제 파일을 가리 키지 만 stderr은 여전히 ​​터미널을 가리 킵니다! stderr에 기록되는 모든 내용이 여전히 화면에 인쇄됩니다! 따라서 리디렉션 순서에 매우주의하십시오!

또한 Bash에서 다음과 같이 작성하십시오.

$ 명령 &> 파일

정확히 다음과 같습니다.

$ 명령> & file


답변

숫자는 파일 디스크립터 (fd)를 나타냅니다.

  • 제로 stdin
  • 하나는 stdout
  • stderr

2>&1 fd 2를 1로 리디렉션합니다.

프로그램에서 사용하는 파일 디스크립터 수에 관계없이 작동합니다.

/usr/include/unistd.h잊어 버린 경우 살펴볼 수 있습니다 .

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

즉, 사용자 정의 로깅에 비표준 파일 디스크립터를 사용하는 C 도구를 작성 했으므로 파일이나 파일로 리디렉션하지 않으면 볼 수 없습니다.


답변

이 구문은 표준 오류 스트림 ( stderr)을 표준 출력 ( ) 의 현재 위치로 보냅니다. stdout이 통화 문제는 다른 답변에서 무시 된 것으로 보입니다.

이 방법을 사용하여 출력 핸들을 다른 출력 핸들로 리디렉션 할 수 있지만 처리를 위해 단일 스트림으로 채널링 stdoutstderr스트리밍 하는 데 가장 많이 사용됩니다 .

몇 가지 예는 다음과 같습니다.

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

마지막 한 점에 유의 하지 지시 stderroutfile2– 그것은 무엇에 리디렉션 stdout인수가 발견되었을 경우에 (했다 outfile1)와 다음은 리디렉션 stdoutoutfile2.

이것은 꽤 정교한 속임수를 허용합니다.


답변

2>&1POSIX 쉘 구조입니다. 다음은 토큰 별 분류입니다.


2: ” 표준 오류 “출력 파일 설명자.

>&: 출력 파일 디스크립터 연산자 ( 출력 재 지정 연산자 의 변형)를 복제합니다> . 주어지면 [x]>&[y], 파일 디스크립터에 의해 표시 x출력 디스크립터 파일의 복사본으로 이루어진다 y.

1표준 출력 “출력 파일 디스크립터.

이 표현식 2>&1은 파일 디스크립터 1를 location에 복사 2하므로 2실행 환경에서 ( “표준 오류”)로 기록 된 출력 은 원래 1“표준 출력”으로 설명 된 것과 동일한 파일로 이동합니다 .


추가 설명 :

File Descriptor : “파일 액세스를 위해 열린 파일을 식별하는 데 사용되는 프로세스 별 고유 한 음이 아닌 정수입니다.”

표준 출력 / 오류 : 쉘 설명서 의 리디렉션 섹션 에서 다음 참고 사항을 참조하십시오 .

열린 파일은 0으로 시작하는 10 진수로 표시됩니다. 가능한 최대 값은 구현 정의입니다. 그러나 모든 구현은 응용 프로그램에서 사용하기 위해 0-9 이상을 지원해야합니다. 이 번호를 “파일 디스크립터”라고합니다. 값 0, 1 및 2는 특별한 의미와 일반적인 용도를 가지며 특정 리디렉션 작업에 의해 암시됩니다. 이를 각각 표준 입력, 표준 출력 및 표준 오류라고합니다. 프로그램은 일반적으로 표준 입력에서 입력을 가져 와서 표준 출력에 출력을 씁니다. 오류 메시지는 일반적으로 표준 오류로 작성됩니다. 경로 재 지정 연산자 앞에는 파일 설명자 번호를 지정하기 위해 하나 이상의 숫자 (개입 문자가 허용되지 않음)가있을 수 있습니다.