stdout fd를 닫으면 오류가 발생하지만 stderr fd를 닫으면 오류가 발생하지 않습니다.

stdout fd를 닫으면 오류가 발생하지만 stderr fd를 닫으면 오류가 발생하지 않습니다.

다음 테스트 코드는 "잘못된 파일 설명자" 오류를 제공합니다. 왜 이런 일이 발생합니까? 이는 파일 설명자와 파이프와의 상호 작용을 이해하기 위한 테스트 코드일 뿐입니다.

예시 1)

❯ echo "hello" 1>&2 1>&- |& echo "world"
world
zsh: 1: bad file descriptor

예시 2)

echo "hello" 1>&2 1>&- | cat <<< "world"
zsh: write error: bad file descriptor
world

예시 3)

# Does not give error
❯ echo "helloworld" >&-
# Gives stdin? error
❯ cat <<< "helloworld" >&-
cat: stdin: Bad file descriptor

stderr을 닫거나 stdout과 stderr을 모두 닫으면 "잘못된 파일 설명자" 오류가 발생하지 않습니다. 예를 들어 다음 중 어느 것도 오류를 발생시키지 않습니다.

❯ echo "hello" 1>&2 2>&- |& echo "world"
❯ echo "hello" 2>&1 2>&- |& echo "world"
❯ echo "hello" 1>&2 1>&- 2>&- |& echo "world"

답변1

|&2>&1 |(예:녹음된). 왼쪽의 표준 출력은 다른 리디렉션이 수행되기 전에 파이프의 쓰기 측에 연결되지만 표준 오류는 마지막에 당시의 표준 출력에 연결됩니다. 이는 표준 출력이 리디렉션되거나 예에서와 같이 닫히는 경우 영향을 미칩니다. foo 1>&- |& bar, 또는 이와 동등한 것을 사용하거나 foo 1>&- 2>&1 | bar단지 사용하면 foo 1>&- 2>&1fd 2에서 fd 1로의 리디렉션이 적용될 때 파일 설명자 1에 아무것도 없습니다.

를 사용하는 경우 foo 1>&2 1>&- | bar먼저 foo표준 출력을 파이프의 쓰기 끝에 연결한 다음( multios열려 있다고 가정) 1>&2내장된 T자형 프로세스에 대한 파이프를 생성합니다. 이 프로세스는 |운영자가 생성한 파이프와 파일에 기록합니다. 당시의 설명자 2(즉, 터미널). 그런 다음 표준 출력이 1>&-닫히므로 foo표준 출력에 쓰려고 하면 이 쓰기가 실패합니다. 티와 같은 프로세스가 쓰는 위치가 아무리 많아도 1>&-입력을 받을 수 없습니다.

^ 문서에서 지정된 것을 찾을 수 없지만 이것이 쉘이 전통적으로 수행한 작업입니다.POSIX에 의해 지정됨. 확실하지 않은 경우 소스 코드, 시스템 호출 추적을 확인하거나 다양한 리디렉션 실험(예: 지금까지 실행한 실험)의 결과에서 추론할 수 있습니다.

관련 정보