> /-가> / dev / null보다 효율적입니까? >&-구문이 “파일 디스크립터를

어제 본인은 이 SO 의견을 쉘에서 (적어도 있다고한다 bash) >&-“와 같은 결과가 있습니다” >/dev/null.

이 의견은 실제로 ABS 안내서 를 정보의 출처로 언급합니다 . 그러나 그 소스는 >&-구문이 “파일 디스크립터를 닫는다” 고 말합니다 .

파일 디스크립터를 닫고 널 디바이스로 경로 재지 정하는 두 가지 조치가 완전히 동등한 지 여부는 확실하지 않습니다. 그래서 내 질문은 : 그들이 있습니까?

표면적으로 설명자를 닫는 것은 문을 닫는 것과 같지만 널 장치로 리디렉션하면 림보의 문이 열립니다! 닫힌 문을 보면 아무것도 버리려고하지 않지만 열린 문을 보면 내가 할 수 있다고 가정하기 때문에 두 사람은 나에게 똑같이 보이지 않습니다.

즉, 실제로 파일의 모든 바이트를 처리하고 잊어 버릴 수 있는 >/dev/null수단이 있는지 항상 궁금 했습니다. 다른 한편으로, 쉘이 닫힌 파일 디스크립터를 만나면 단순히 아무것도 쓰지 않을 것이라고 생각하는 경향이 있지만 확실하지는 않지만 모든 바이트를 읽을 지 여부 는 여전히 의문 입니다.cat mybigfile >/dev/null/dev/nullcat

이 코멘트는 말했다 >&->/dev/null해야 동일”하지만 나에게 이렇게 울려 퍼지는 대답하지 않습니다. 표준 또는 소스 코어와 관련하여 더 권위있는 답변을 원합니다.



답변

아니요, 파일 디스크립터 0, 1 및 2를 닫고 싶지 는 않습니다 .

이렇게하면 응용 프로그램이 파일을 처음 열 때 stdin / stdout / stderr가됩니다 …

예를 들어, 다음과 같은 경우 :

echo text | tee file >&-

tee(비지 박스 같은 적어도 일부 구현 ‘) 쓰기 위해 파일을 열어,이 파일 기술자 1 (표준 출력)에 공개됩니다. 그래서 두 번 tee쓸 것입니다 :textfile

$ echo text | strace tee file >&-
[...]
open("file", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 1
read(0, "text\n", 8193)                 = 5
write(1, "text\n", 5)                   = 5
write(1, "text\n", 5)                   = 5
read(0, "", 8193)                       = 0
exit_group(0)                           = ?

보안 취약점을 일으키는 것으로 알려져 있습니다. 예를 들어 :

chsh 2>&-

그리고 chsh(setuid 애플리케이션)은에 오류 메시지를 작성할 수 있습니다 /etc/passwd.

일부 도구 및 일부 라이브러리는이를 방지하려고합니다. 예를 들어 teebusybox tee는 작성하지 않고 쓰기 위해 열린 파일에 0, 1, 2가 할당 된 경우 GNU 는 파일 디스크립터를 2 이상으로 이동합니다 .

대부분의 도구가 stdout에 쓸 수없는 경우 (예 : 열려 있지 않기 때문에) 현지화 파일을 열고 구문 분석하는 추가 처리를 의미하는 사용자의 언어로 stderr에 오류 메시지를보고합니다. 효율성이 크게 떨어지고 프로그램이 실패 할 수 있습니다.

어쨌든 더 효율적이지 않습니다. 프로그램은 여전히 write()시스템 호출을 수행합니다 . 첫 번째 write()시스템 호출 실패 후 프로그램이 stdout / stderr에 쓰기를 포기하는 경우에만 더 효율적일 수 있지만 프로그램은 일반적으로 그렇게하지 않습니다. 일반적으로 오류와 함께 종료되거나 계속 시도합니다.


답변

IOW는 항상 파일의 모든 바이트를 실제로 처리하고 잊어 버릴 수 있는 >/dev/null수단인지 궁금 했습니다.cat mybigfile >/dev/null/dev/null

귀하의 질문에 대한 완전한 답변은 아니지만 위의 방법이 작동합니다.

cat명명 된 파일 또는 명명 된 파일이없는 경우 표준 입력을 읽고 명명 된 마지막 파일에서 EOF (표준 입력 포함)가 발생할 때까지 해당 내용을 표준 출력에 출력 합니다. 즉 작업.

추가 >/dev/null하면 표준 출력을 / dev / null로 리디렉션합니다. 그것은 특별한 파일 (장치 노드)로 쓰여진 것을 버리고 (읽을 때 즉시 EOF를 반환합니다). I / O 리디렉션은 각각의 개별 응용 프로그램이 아니라 셸에서 제공하는 기능이며 / dev / null 이라는 이름 에는 마법적인 것이 없으며 대부분의 Unix 계열 시스템 에는 존재하는 것만 있습니다 .

그것은 장치 노드의 특정 메커니즘이 운영 운영 체제 시스템,하지만 고양이 (A GNU 시스템에서,로 coreutils을 의미한다)에서 차이가 있음을 크로스 플랫폼입니다주의하는 것도 중요하다 (동일한 소스 코드를 실행하는 데 필요한 최소한 리눅스와에 Hurd) 따라서 특정 운영 체제 커널에 종속 될 수 없습니다. 또한 다른 이름으로 / dev / null 별칭 (Linux에서는 주 / 부 장치 번호가 동일한 장치 노드를 의미 함)을 만들면 여전히 작동합니다. 그리고 항상 동일하게 동작하는 다른 곳 (예 : / dev / zero)을 작성하는 경우가 있습니다.

그것은 cat/ dev / null의 특별한 속성을 알지 못하기 때문에 처음에는 리디렉션을 알지 못할 수도 있지만 여전히 똑같은 작업을 수행해야 합니다. 명명 된 파일을 읽고 내용을 출력합니다. 해당 파일을 표준 출력에 추가합니다. 표준 출력이 cat빈 공간으로 들어가는 것은 cat그 자체가 우려하는 것이 아닙니다 .


답변