이 명령의 리디렉션을 이해하시나요? [복사]

이 명령의 리디렉션을 이해하시나요? [복사]

마법의 명령을 찾았어요여기

./my.sh 3>all 1> >(tee out >&3) 2> >(tee err >&3)

내가 혼란스러워하는 곳이 있습니다.

  1. 3>allfile 에 대해 파일 설명자 3을 설정한다는 의미 입니까 all?
  2. 무엇을 해야 1> >할까요 2> >? 내 이해에 따르면 명령은 이어야 ./my.sh 3>all 1>(tee out >&3) 2>(tee err >&3)하지만 작동하지 않습니다.
  3. (tee err >&3)파일을 덮어쓰지 않는 이유는 무엇입니까 all?

이 내 꺼야my.sh

#!/bin/bash

echo myecho
ls dflj

답변1

Bash 매뉴얼 페이지에서 이 구문에 대해 읽을 수 있습니다.프로세스 대체:

>(list). 프로세스목록실행되면 해당 출력이 /dev/fd의 파일에 연결됩니다. 파일 이름은 확장 결과로 현재 명령에 인수로 전달됩니다.

이 명령의 출력을 보면 리디렉션이 수행되지 않습니다.

echo >(echo hi >/tmp/a) >(echo lo >/tmp/b)

그것은 (내 시스템에서):

/dev/fd/63 /dev/fd/62

그러므로 and 1> >(...)로 읽어야 합니다 . 두 번째 부분은 로 대체된 다음 stdout을 파일 설명자 63으로 리디렉션합니다. 1>>(...)/dev/fd/631> /dev/fd/63

bash는 별도의 프로세스에서 명령을 실행 >(...)하고 해당 프로세스의 표준 입력을 파일 설명자 63에 연결합니다. 다음 예를 확인하세요.

set -x
echo hello > >(cat -n)

Echo의 표준 출력은 입력으로 연결되어 cat -n다음을 얻습니다.

+ echo hello
++ cat -n
 1  hello

아마도 당신이 놓치고 있는 것은 당신이파일 설명자(fd)가 파일이면십자가프로세스(bash가 사용하는 프로세스 >(...))를 사용하면 새 프로세스에서 동일한 fd를 상속받을 수 있습니다. 따라서 이 두 프로세스는 동일한 fd를 공유합니다. 게다가 딱 하나 있는데파일 오프셋fd의 경우 프로세스 1이 fd에 3자를 쓰면 오프셋은 0에서 3으로 이동합니다. 프로세스 2가 fd에 5개의 문자를 쓰면 데이터는 오프셋 3에 배치되고 오프셋은 8이 됩니다. 프로세스 2 1이 다른 문자를 쓰면 오프셋 8에 배치됩니다. 이것이 귀하의 질문에 있는 tee두 명령이 all서로 덮어쓰지 않고 동일한 파일에 쓰는 방법입니다.

를 사용하면 >&3새 fd가 생성되지 않습니다. 단지 현재 stdout fd 1을 닫은 다음 fd 3의 번호를 fd 1로 다시 지정합니다. 따라서 이제 각 프로세스에 다른 숫자가 표시되더라도( man dup2기본 시스템 호출 참조) 두 프로세스 모두에 대해 여전히 하나의 fd만 ​​있습니다.

답변2

meuh의 훌륭한 이론적 답변보다 문자 그대로 설명하려고 하면 아마도 알고 있듯이 기본 파일 설명자가 많이 있습니다.

  • 0표준 입력을 의미합니다.
  • 1표준 출력을 의미합니다.
  • 2표준 오류를 나타냅니다.

명령은 다음을 수행합니다.

  • 3>all파일을 가리키는 새 파일 설명자를 엽니다.all
  • 1> >(tee out >&3)meuh가 설명한 대로 stdout( 1)을 tee 명령에 의해 열리고 반환된 파일 설명자로 리디렉션합니다.
    • tee out >&3입력(이 경우 스크립트의 표준 출력)을 out이라는 이름의 파일로 리디렉션하고 3파일 설명자가 가리키는 위치(이 경우 파일은 모두)
  • 2> >(tee err >&3)meuh가 설명한 대로 stderr( 2)을 tee 명령에 의해 열리고 반환된 파일 설명자로 리디렉션합니다.
    • tee err >&3입력(이 경우 스크립트의 stderr)을 err이라는 파일로 리디렉션하고 3파일 설명자가 가리키는 위치(이 경우 파일 all)

>>귀하의 의견을 보면 혼란스러운 점은 출력을 파일에 추가하려는 경우 리디렉션 연산자를 사용해야 한다는 것입니다.

여기서는 그렇지 않습니다. 실제로 수행하는 작업은 stdout과 stderr을 파일 all을 가리키는 파일 설명자에 연결하는 것뿐입니다.

효과는 다음과 같습니다.

./my.sh > all 2>&1

먼저 stdout을 all 파일로 리디렉션한 다음 stderr를 stdout이 가리키는 곳으로 리디렉션합니다.

관련 정보