파일 설명자 셔플링 및 /dev/fd를 통한 두 개의 입력 파이프

파일 설명자 셔플링 및 /dev/fd를 통한 두 개의 입력 파이프

두 개의 프로그램을 하나로 연결하고 싶습니다. 내 쉘이 지원한다면 사용할 수 있습니다프로세스 대체. 예를 들어, 두 파일의 공통 행을 무관한 순서로 나열하려면 다음을 사용할 수 있습니다.

comm -12 <(sort a) <(sort b)

그러나 프로세스 대체는 plain 에 존재하지 않습니다 sh. 나는 다음을 생성하여 완전한 POSIX 이식성을 가지고 이를 수행할 수 있습니다.명명된 파이프, 그러나 FIFO용 디렉터리를 찾고 나중에 정리해야 하므로 번거롭습니다. 실용적인 좋은 절충안은 두 개의 쉘 파이프 구성을 사용하고 파일 설명자 섞기를 사용하여 한 파이프를 다른 파일 설명자로 이동한 다음 이를 사용하여 /dev/fd대부분의 Unix 변형에서 작동하는 파이프를 지정하는 것입니다.

sort a | { exec 3<&0; sort b | comm -12 /dev/fd/0 /dev/fd/3; }

이는 dash, bash, BusyBox sh 등에서는 작동하지만 ksh93 및 mksh에서는 작동하지 않습니다. 왜?

$ mksh -c 'sort a | { exec 3<&0; sort b | comm -12 /dev/fd/0 /dev/fd/3; }'
$ ksh93 -c 'sort a | { exec 3<&0; sort b | comm -12 /dev/fd/0 /dev/fd/3; }'
comm: /dev/fd/0: No such device or address

답변1

다른 명령의 리디렉션과 달리 exec내장된 리디렉션은 쉘이 외부 프로그램을 실행할 때 닫힐 수 있습니다.POSIX는 두 가지 동작을 모두 허용합니다.. Ksh(ATT ksh, pdksh 및 mksh 모두)는 외부 유틸리티를 실행할 때 이러한 설명자를 닫습니다(즉, 내장된 리디렉션의 경우 리디렉션을 수행하기 위해 exec호출한 후 새 설명자에 플래그를 설정합니다). Bourne 쉘, dash, bash, zsh 및 BusyBox sh는 이 리디렉션을 다른 리디렉션과 마찬가지로 처리합니다.dup2FD_CLOEXEC

두 개의 입력 파이프 문제(가 있다고 가정 /dev/fd)에 대한 보다 이식 가능한 솔루션은 입력을 읽는 명령에 대해 또 다른 리디렉션을 수행하여 파일 설명자를 새 설명자로 이동하는 것입니다. 이 추가 리디렉션은 새 설명자에 close-on-exec 플래그를 설정하지 않습니다.

sort a | { exec 3<&0; sort b | comm -12 /dev/fd/0 /dev/fd/4 4<&3; }

이는 pdksh/mksh 및 ksh93r에서는 작동하지만 최신 버전의 ksh(93s+ 2008-01-31 또는 93u+ 2012-08-01)에서는 작동하지 않습니다. 나는 ksh가 거기서 무엇을 하고 있는지 이해하지 못합니다.

관련 정보