OS X, bash: 열린 파일 설명자에서는 덜 작동하지만 cat은 작동하지 않습니다.

OS X, bash: 열린 파일 설명자에서는 덜 작동하지만 cat은 작동하지 않습니다.

제가 작업 중인 bash 스크립트(Ubuntu 및 OS X에서 실행되어야 함)에서 수백 개의 명령 출력을 파일로 리디렉션해야 합니다. 이 모든 것을
추가하는 대신 간단히 추가했습니다.&>...

exec 9>&1
exec 5<>/tmp/some-file.txt
exec 1>&5

지금까지는 괜찮았지만, 이 모든 명령을 수행하는 동안 파일 설명자를 열어둔 채 지금까지 작성된 모든 내용을 읽어야 합니다.
이제 우분투에서는 간단히 할 수 있습니다

cat /dev/fd/5

또는

tee </dev/fd/5

그러나 OS X에서는 아무 것도 인쇄되지 않습니다(그리고 명령은 즉시 종료됩니다).
그러나 less파일의 내용은 I를 사용하여 두 가지 모두에서 볼 수 있습니다.
다음을 사용하여 위의 효과(두 OS 모두에서 작동)를 달성할 수 있었습니다.

less /dev/fd/5 | tee

하지만 이건 해킹인 것 같습니다.

less그렇다면 OS X에서는 볼 수 없는 것을 보는 것이 분명히 가능한 이유는 무엇입니까 ? cat(아니면 모든 BSD 자손이 영향을 받나요?)
아니면 제가 뭔가 잘못하고 있는 걸까요?

답변1

OS X에서는 이를 지원하는 모든 시스템과 마찬가지로리눅스 제외/dev/fd/x, a 실행과 마찬가지로 열면 dup(x)결과 fd는 fd x와 거의 동일한 열린 파일 설명, 특히 파일 내에서 동일한 오프셋을 가리킵니다.

여기서는 Linux는 예외입니다. Linux에서는 /dev/fd/xfd x 에서 열린 파일에 대한 기호 링크 /proc/self/fd/x이자 /proc/self/fd/x의사 기호 링크입니다. Linux에서는 를 실행하면 open("/dev/fd/x", somemode)완전히 새로운 것을 얻게 됩니다.파일 설명 열기열린 파일과 동일한 파일에 x. 당신이 얻는 새로운 fd는 fd x와 아무 관련이 없습니다. 특히 오프셋은 파일의 시작 부분에 있습니다(물론 O_APPEND역방향 모드에서 파이프를 열 때 다른 쪽 끝에서 열지 않는 한 ). (이것은 또한 소켓에서는 작동하지 않는다는 것을 의미합니다.열려 있는()).

따라서 Linux에서는 다음과 같은 작업을 수행할 때

exec 5<> file
echo test >&5

fd 5의 오프셋은 파일 끝에 있습니다. 당신이 그렇게한다면

cat <&5

당신은 아무것도 얻지 못합니다.

또는 다음을 수행할 때:

cat /dev/fd/5

보시다시피 test, fd 5와 아무 관련이 없는 새로운 읽기 전용 fd가 얻어지기 때문입니다 cat.file

다른 시스템에서는

cat /dev/fd/5

catfd 5와 중복된 fd를 가져오면 파일 끝에 여전히 오프셋이 있습니다.

이것이 작동하는 이유 는 어떤 이유로 a가 less해당 fd에서 파일 시작 부분까지 less실행되기 때문입니다(a는 파일을 검색할 수 있는지 확인하기 위해 실행됩니다).lseek()lseek(1); lseek(0)

여기서 두 fd가 서로 다른 오프셋을 갖도록 하려면 읽기용 fd 하나와 쓰기용 fd 하나를 갖고 싶을 수 있습니다.

exec 5< file 9>&1 > file

또는 파일이 여전히 존재하는 경우 해당 파일을 다시 열거나 lseek()동일한 less작업을 수행해야 합니다.

ksh93연산자가 내장된 zsh유일한 쉘입니다 :lseek()

cat <&5 <#((0)) # ksh93
{sysseek 0; cat} <&5 # zsh, zmodload zsh/system to enable that builtin

또는:

cat /dev/fd/5 5<#((0))  # ksh93
sysseek -u 5 0; cat /dev/fd/5 # zsh

관련 정보