zsh는 이 명령이 완료될 때까지 기다리지만 bash는 명령이 완료되기 전에 프롬프트에 기록하는 이유는 무엇입니까?

zsh는 이 명령이 완료될 때까지 기다리지만 bash는 명령이 완료되기 전에 프롬프트에 기록하는 이유는 무엇입니까?

이것은 명령입니다:

{ ( echo "to stdout"; echo "to stderr" >&2 ) > >(sleep 1; tee stdout.txt); } 2> >(sleep 2; tee stderr.txt >&2 )

이것이 내가 보는 것입니다:

다루기 힘든

% { ( echo "to stdout"; echo "to stderr" >&2 ) > >(sleep 1; tee stdout.txt); } 2> >(sleep 2; tee stderr.txt >&2 )
to stdout
to stderr
%

세게 때리다

$ { ( echo "to stdout"; echo "to stderr" >&2 ) > >(sleep 1; tee stdout.txt); } 2> >(sleep 2; tee stderr.txt >&2 )
$ to stdout
to stderr

bash는 출력이 완료되기 전에 프롬프트를 작성 $하지만 zsh는 사용자에게 프롬프트를 표시하기 전에 교체 프로세스가 완료될 때까지 기다립니다 %.

합리적인 대답은 "그게 zsh가 작동하는 방식이기 때문입니다"라고 생각합니다. 그러나 이것이 더 많은 것을 배울 수 있도록 어디에 문서화되어 있는지 알고 싶습니다. 많은 bash 사용자 중 zsh 사용자로서 저는 "이 명령을 실행해 보세요"라고 말하면 어떤 일이 발생하는지 알 수 있도록 차이점을 이해하려고 노력합니다.

(관련 질문:https://stackoverflow.com/a/53051506/1054322)

답변1

더 짧은 예는 두 쉘 모두에서 동일한 방식으로 작동합니다. 상위 쉘은 기다리지 않습니다.

(sleep 1; echo done) > >(cat >file) &

다음과 같이 수정하면,zsh ~ 할 것이다잠깐만요. 하지만 bash그렇지는 않습니다:

{ (sleep 1; echo done) & } > >(cat >file)

zshexpn(1)유사한 예가 매뉴얼의 "PROCESS SUBSTITUTION"에 나와 있습니다. 거기 { ... }에는 비동기 프로세스의 출력을 프로세스 대체(두 셸 모두에서 비동기임)로 리디렉션할 때 셸이 비동기 프로세스를 기다리지만 { ... }.

설명서에는 문제가 다음과 같이 설명되어 있습니다.

>(process)외부 명령에 연결하면 추가적인 문제가 발생합니다 .상위 셸은 프로세스가 완료될 때까지 기다리지 않으므로 뒤따르는 명령은 완료 결과에 의존할 수 없습니다..

비동기 명령을 복합으로 캡슐화함으로써 { ... }"여기의 추가 프로세스는 상위 셸에서 생성되고 상위 셸은 완료될 때까지 기다립니다." 이에 대한 내 해석은 우리가 리디렉션하는 프로세스가 >(...)셸에서 생성되는 반면, 그렇지 않은 프로세스는 { ... }백그라운드 작업으로 시작한 작업에서 생성된다는 것입니다(그래서 셸은 이를 기다리지 않습니다).

$ZSH_SUBSHELL리디렉션하는 프로세스 교체에서 출력을 가져오면 이에 대한 증거를 찾을 수 있습니다. 차단 코드의 경우 를 출력하고 1, 비차단 코드의 경우 를 출력합니다. 이는 2출력이 다른 하위 쉘 내에서 하위 쉘로 실행되도록 리디렉션됨을 나타냅니다(메인 쉘은 기다리지 않음).

출력 프로세스 교체의 출력이 에서와 동일한 동작을 나타내 더라도 쉘은 bash이를 다르게 처리하고 두 경우 모두 상위 쉘과 독립적으로 모든 백그라운드 작업을 생성하는 것으로 보입니다 .$BASH_SUBSHELLzsh

관련 정보