파일 설명자 셔플링 및 /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내장 프로그램에 대한 리디렉션 의 경우 dup2리디렉션을 수행하기 위해 호출 후 FD_CLOEXEC새 설명자에 플래그를 설정합니다 ). Bourne Shell, dash, bash, zsh 및 BusyBox sh는 이 리디렉션을 다른 리디렉션으로 처리합니다.

이중 입력 파이프 문제(존재한다고 가정 /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가 거기서 무엇을 하고 있는지 이해하지 못합니다.

관련 정보