`>()` 하위 쉘이 리디렉션의 일부인 경우(예: `> >()`) 표준 출력이 다른 이유는 무엇입니까?

`>()` 하위 쉘이 리디렉션의 일부인 경우(예: `> >()`) 표준 출력이 다른 이유는 무엇입니까?

이것은 다음에 대한 후속 질문입니다.`... > >(sed 's/^/stdout: /')`가 인쇄되지 않는데 `... | sed 's/^/stdout: /'`가 빈 표준 입력에 인쇄되는 이유는 무엇입니까?

보다 구체적으로 이것이 파이프인 이유는 다음과 같습니다.

$ tee 2> >(readlink /proc/self/fd/1) < /dev/null | cat        
pipe:[17955449]

이것이 최종 장치인 경우는 언제입니까? :

$ tee >(readlink /proc/self/fd/1) < /dev/null | cat   
/dev/pts/31

나는 전자의 출력이 명령을 입력한 쉘에서 자연스럽게 상속될 것이라고 생각했을 것입니다. 그러나 bash와 zsh 모두 리디렉션되도록 명령의 출력을 리디렉션하기 위해 명시적인 단계를 수행해야 하는 것 같습니다. 그들은 왜 이런 일을 하는가? 아니면 다른 일이 일어나고 있나요? 전자의 서브쉘은 tee'ing' 이전 프로세스에서 생성됩니까? 하나의 하위 쉘은 하위 프로세스에서 상속되고 다른 하위 쉘은 상위 프로세스에서 상속됩니까? 어떻게?exectee

흠... 태깅하고 확인하는 동안 bash두 경우 모두 bash의 파이프라는 것을 알았습니다... 그래서 이것은 zsh 기능입니다.

답변1

zsh는 동일한 명령에 대한 다중 리디렉션을 지원합니다. 예를 들어, abc > def > ghi전체 출력을 abcsum def에 넣습니다 ghi. 또한 두 개와 >하나의 장식되지 않은 리디렉션을 동시에 허용합니다. 이는 첫 번째 예에서 사용한 리디렉션입니다.|

여러 리디렉션의 경우 프로세스가 리디렉션으로 대체됩니다.

tee 2> >(readlink /proc/self/fd/1) < /dev/null | cat

출력은 기본 명령과 마찬가지로 파이프로 연결되며 프로세스 교체를 해당 명령으로 리디렉션할 필요가 없습니다.

tee >(readlink /proc/self/fd/1) < /dev/null | cat

아니요. 파이프라인은 리디렉션된 분기의 모든 출력이 파이프라인을 통과한다는 점에서 우선순위를 갖습니다. 이 경우 두 개의 분기(주 명령 자체와 프로세스 교체의 출력)가 있으며 둘 다 통과되므로 cat둘 다 표준 출력을 파이프로 처리합니다.

Bash는 항상 대체 항목을 사용자에게 파이프 cat하며 처음에는 이와 같은 여러 리디렉션을 지원하지 않습니다.

본질적으로,zsh에서 여러 리디렉션이 있음, 여전히 하나만 있을 수 |있으며파이프라인은 리디렉션의 모든 분기에 분산됩니다., 하지만프로세스 대체 자체는 프로세스 대체의 일부가 아닙니다.- 실제 출력 리디렉션만 가능합니다 >.

이는 프로세스 대체를 통해 표시되는 리디렉션의 속성입니다. 리디렉션된 프로세스 대체와 리디렉션되지 않은 프로세스 대체를 모두 사용할 수 있으며 다음을 확인할 수 있습니다.

$ true >( readlink /proc/self/fd/1 ) > >( readlink /proc/self/fd/1 ) | cat
/dev/tty1
pipe:[2975]

첫 번째(대체)는 TTY를 표준 출력으로 사용하고, 두 번째(리디렉션)는 입력을 cat. 이것이 이 설정을 구축하는 유일한 간단한 방법입니다. 즉, 파이프로 연결된 명령의 단일 인스턴스와 그 앞에 파이프된 명령과 파이프되지 않은 명령이 혼합된 것입니다. 원하지 않을 때 잘못된 트랙에서 출력을 리디렉션하게 되면 복구를 사용할 수 있지만 > /dev/pts/...Bash에서와 같이 기본 교체 리디렉션을 정말로 원한다면 여전히 운이 좋지 않습니다.

프로세스 교체 자체는 셸에서 환경을 상속하고 리디렉션은 파이프의 요소뿐만 아니라 입력 및 출력도 수정합니다. 내 생각엔 이건 아닌 것 같아필요한이는 다음과 같이 작동하지만 하나의 일관된 규칙을 따릅니다.|항상 에 배포되지만 >매개변수는 무시됩니다..

내 실험은 실제 동작을 설명하지만 여기에 인라인으로 포함하기에는 너무 길고 다루기 힘들지만이 답변의 개정 내역에서. 아래에는 네 가지 상황(예/아니요 >및 )과 해당 동작을 요약했습니다 |.


사례 분석

일반적으로 zsh는 네 가지 경우에 작동합니다.

  1. |, 아니요>

    abc >( def ) | ghi
    

    이는 기본 명령의 출력을 파이프로 보내고, 서브셸의 출력을 TTY로 보내고, 경로를 abc.

  2. 아니 |아니>

    abc >( def )
    

    그러면 모든 것이 TTY로 전송되고 경로가 abc.

  3. 아니 |, 하지만>

    abc > >( def )
    

    이는 인수를 제공하지 않고 기본 명령의 출력을 서브쉘로 보내고 서브쉘을 TTY로 보냅니다 abc.

  4. |그리고>

    abc > >( def ) | ghi
    

    그러면 기본 명령의 출력이 다음으로 전송됩니다.둘 다프로세스 대체 및 파이프는 물론 서브쉘에서 파이프로의 출력도 제공하지 않습니다 abc.abc | tee >( def ) | ghi

나는 사례 4가 사례 1과 너무 달라서 변화가 파이프에서 너무 멀리 떨어져 있는 것처럼 느껴지지만 그것이 바로 그 점을 정말 좋아하지 않습니다.

관련 정보