>&- >/dev/null보다 더 효율적인가요?

>&- >/dev/null보다 더 효율적인가요?

어제 나는 읽었다이 댓글이는 쉘에서 (적어도 bash) >&-"와 동일한 결과가 있음을 의미합니다" >/dev/null.

이 댓글은 실제로 다음을 참조합니다.ABS 가이드정보의 출처로. 그러나 소스에서는 >&-구문이 "파일 설명자를 닫습니다"라고 말합니다.

파일 설명자를 닫는 것과 이를 빈 장치로 리디렉션하는 것이 정확히 동일한지는 확실하지 않습니다. 그래서 내 질문은: 그렇습니까?

표면적으로 설명자를 닫는 것은 문을 닫는 것과 같지만, 이를 빈 장치로 리디렉션하는 것은 지옥의 문을 여는 것과 같습니다! 나에게 그 둘은 정확히 똑같지 않은 것 같습니다. 왜냐하면 닫힌 문이 보이면 아무것도 던지지 않으려고 하지만 열린 문이 보이면 던질 수 있다고 생각하기 때문입니다.

즉, >/dev/null이것이 cat mybigfile >/dev/null실제로 파일의 모든 바이트를 처리하고 /dev/null잊어버린 곳에 쓰는 것을 의미하는지 궁금합니다. 반면에 쉘이 닫힌 파일 설명자를 만나면 아무 것도 쓰지 않을 것이라고 생각하는 경향이 있습니다(확실하지는 않지만). 그래도 cat여전히 쓸 것인지에 대한 의문은 남아 있습니다.읽다바이트당.

이 댓글">&- 라고 말하다>/dev/null~해야 한다"동일하지만 제게는 그렇게 와닿는 대답은 아닙니다. 좀 더 권위 있는 대답을 듣고 표준이나 소스 코어를 참고하든 말든...

답변1

아니, 물론이지 너는아니요파일 설명자 0, 1, 2를 닫고 싶습니다.

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

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

echo text | tee file >&-

(적어도 busybox'와 같은 일부 구현에서는) 쓰기 위해 파일을 열면 tee파일 설명자 1(stdout)에서 열립니다. 따라서 두 번 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.

일부 도구와 일부 라이브러리는 이러한 일이 발생하는 것을 방지하려고 합니다. 예를 들어, teeGNU가 쓰기 위해 연 파일에 0, 1, 2가 할당되면 GNU는 파일 설명자를 2 위로 이동하지만 busybox는 tee그렇지 않습니다.

대부분의 도구는 표준 출력에 쓸 수 없는 경우(예를 들어 열려 있지 않기 때문에) 표준 오류에 대한 오류 메시지를 보고합니다(사용자의 언어로, 이는 현지화된 파일을 열고 구문 분석하는 추가 처리를 의미함...). .), 따라서 효율성이 크게 감소하고 프로그램이 실패할 수 있습니다.

결코 더 효율적이지 않습니다. 프로그램은 여전히 write()​​시스템 호출을 수행합니다. 프로그램이 첫 번째 시스템 호출 실패 후 stdout/stderr에 대한 쓰기를 포기한 경우에만 더 효율적이지만 write()프로그램은 일반적으로 이를 수행하지 않습니다. 일반적으로 오류가 발생하여 종료되거나 계속 시도됩니다.

답변2

>/dev/nullIOW 이것이 cat mybigfile >/dev/null실제로 파일의 모든 바이트를 처리하고 /dev/null잊어버린 곳에 쓰는 것을 의미하는지 궁금합니다 .

이것은 귀하의 질문에 대한 완전한 답변은 아니지만, 그렇습니다. 위의 내용은 작동 방식입니다.

cat지정된 파일을 읽고, 파일이 지정되지 않은 경우 표준 입력 및 출력을 읽습니다.표준 출력으로마지막으로 명명된 파일(표준 입력 포함)에서 EOF가 발견될 때까지의 내용입니다. 그건그것은일하다.

추가하면 >/dev/null표준 출력을 /dev/null로 리디렉션할 수 있습니다. 이것은 기록된 모든 내용을 삭제하고 읽을 때 즉시 EOF를 반환하는 특수 파일(장치 노드)입니다. I/O 리디렉션은 개별 애플리케이션이 아닌 셸에서 제공하는 기능이며 I/O 리디렉션에는 특별한 것이 없습니다.이름/dev/null, 대부분의 경우에만 발생합니다.유닉스 계열 시스템.

장치 노드의 정확한 메커니즘은 운영 체제마다 다르지만 cat(GNU 시스템의 coreutils를 나타냄)은 크로스 플랫폼입니다(실행하려면 동일한 소스 코드가 필요함).적어도Linux 및 Hurd) 따라서 특정 운영 체제 커널에 의존할 수 없습니다. 또한 다른 이름으로 /dev/null 별칭을 생성하는 경우(Linux에서는 동일한 주/부 번호를 가진 장치 노드를 의미함) 여전히 작동합니다. 그리고 다른 곳(예: /dev/zero)에 기록해도 동작이 실제로 동일한 경우가 항상 있습니다.

따라서 cat/dev/null의 특별한 속성에 대해 알지 못하고 실제로 리디렉션에 대해서도 처음에는 알지 못할 것입니다.여전히 똑같은 작업을 수행해야 합니다.지정된 파일을 읽고 해당 파일의 내용을 표준 출력으로 출력합니다. 표준 출력이 cat구멍에 들어가는 것은 cat그 자체의 문제가 아닙니다.

관련 정보