프로그램이 표준 입력에서 읽지 않고 파일에서만 읽는 경우 /dev/stdin을 사용해도 안전합니까?

프로그램이 표준 입력에서 읽지 않고 파일에서만 읽는 경우 /dev/stdin을 사용해도 안전합니까?

프로그램 A의 출력을 프로그램 B로 파이프하고 싶습니다. 프로그램 B는 stdin에서 읽기를 지원하지 않고 파일에서만 읽기만 지원합니다. 간단히 A |dev/stdin을 수행할 수 있습니까?

실제로 작동하는 것처럼 보이지만 파이프를 실행할 때 B가 /dev/stdin에서 얻는 유일한 것은 A가 작성한 것임을 확인하고 싶습니다.

답변1

여기

A | B /dev/stdin

B의 stdin은 파이프이므로 /dev/stdin명명된 파이프처럼 동작합니다.

B따라서 다음 대신 파일을 한 번 열고 처음부터 순차적으로 내용을 읽는 경우에만 작동합니다.

  • 형식을 미리 확인하여 일반 파일인지 확인합니다(여기서 파일은 Linux에서는 Named Pipe로 표시되고 Linux에서는 Named Pipe로 표시됩니다).캐릭터 장치대부분의 다른 시스템에서는).
  • 미리 사이즈를 확인하고
  • 여러 번 열릴 거예요
  • 파일에서 찾아야 합니다(커서 위치 변경)(되감기, 끝으로 이동...)
  • mmap()일반 파일에서는 작동하지만 파이프에서는 작동하지 않는 다른 작업이 필요합니다 .

물론 B표준 입력에서는 읽을 수 없습니다. 예를 들어 다음과 같이 다른 파일 설명자를 사용하십시오.프로세스 교체( B <(A)ksh/zsh/bash에서)는 이 문제를 피할 수 있습니다. 이는 또한 B모든 파일 설명자가 임의로 닫혀서는 안 된다는 것을 의미합니다( sudo위의 fds 2에 대해 수행하는 것과 같은 일부 명령처럼).

대부분의 명령은 단순히 파일을 처음부터 끝까지 순차적으로 읽는 반면, 일부 명령은오직표준 입력에서 입력을 수행하는 대신 파일 이름 인수에서 입력을 수행하는 것은 실제로 위에 나열된 이유 때문에 수행할 수 없으므로 마일리지가 다를 수 있습니다.

$ unzip -l file.zip
Archive:  file.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
    48894  2020-12-05 07:35   file
---------                     -------
    48894                     1 file
$ cat file.zip | unzip -l /dev/stdin
Archive:  /dev/stdin
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of /dev/stdin or
        /dev/stdin.zip, and cannot find /dev/stdin.ZIP, period.

infozip 파일은 순차적으로 처리할 수 없는 파일이며, 파일의 실제 데이터에 액세스하려면 먼저 파일 끝에 있는 인덱스를 읽어야 합니다.

1 극단적인 경우로, Linux의 ksh93 쉘은 파이프 대신 소켓 쌍을 사용한다는 점에 유의하십시오.엿볼 수 있는). Linux에서는 /dev/stdin다른 시스템과 같은 특수 문자 장치가 아니기 때문에"마법"실제 파일에 대한 심볼릭 링크. /dev/stdin이 경우 열기가 불가능하기 때문에 작동하지 않습니다.열려 있는콘센트.

$ ksh93 -c 'echo test | cat /dev/stdin'
cat: /dev/stdin: No such device or address

ksh93의 경우 시스템에 관계없이 파이프를 사용하는 프로세스 대체를 사용해야 합니다.

$ ksh93 -c 'cat <(echo test)'
test

답변2

(JdeBP의 의견도 참조하세요)

예, 하지만 권장되는 방법은 을 사용하는 것입니다 /dev/fd/0. 예를 들어 책에 언급되어 있습니다."UNIX 환경의 고급 프로그래밍":

이는 경로명 인수를 사용하는 프로그램이 다른 경로명과 동일한 방식으로 표준 입력 및 표준 출력을 처리하도록 허용합니다.

/dev/fd/0그리고 /dev/stdin같은 장치입니다. 유용한 정보를 많이 보려면 여기를 참조하세요.

관련 정보