다음 bash-fu 코드는 Linux에서는 잘 실행되지만 MacOS에서는 충돌이 발생합니다.
files="foo bar"
echo PROG 1
for file in $files
do
echo $file | tee -a tempfile.txt
done
sort -u tempfile.txt
echo PROG 2
function trick {
for file in $files
do
echo $file | tee -a $1
done
}
trick >(sort -u)
오류는 다음과 같습니다
PROG 1
foo
bar
bar
foo
PROG 2
tee: /dev/fd/63: Bad file descriptor
foo
tee: /dev/fd/63: Bad file descriptor
bar
Linux에서도 PROG 2
동일한 줄이 PROG 1
오류 없이 작성됩니다. MacOS에서는 파이프 핸들이 닫혀 있거나 상속되지 않은 것처럼 보입니다.
위의 내용은 문제를 재현하는 최소한의 예입니다. 사실 저는 연결 출력과 리디렉션 핸들을 많이 다룹니다. 뭔가 영적인 것
function trick {
for file in $files
do
echo $file | tee -a $1 | grep -Eo "^.."
done
}
trick >(sort -u | sed 's|o|x|g')
이 코드는 Bash 4.1에서는 실행되지 않지만 여러 배포판(Arch, Ubuntu 및 Debian)의 Bash 4.4에서는 작동합니다.
답변1
macOS는 매우 오래된 버전과 함께 제공됩니다 bash
. 버그(프로세스에 의해 대체된 파일 설명자가 tee
이 컨텍스트에서 호출되기 전에 닫혔음)가 최신 버전에서 수정되었습니다. Linux에서 /dev/fd/x
bash 3.2를 사용할 때 동일한 문제(구현이 다르기 때문에 다른 오류 메시지가 표시됨)가 발생합니다 .
zsh
여기에서는 or를 대신 사용할 수 있습니다 ksh93
. bash
아무튼 여기는 피하는 게 좋은 것 같아요.프로세스 교체 중 프로세스를 기다리지 않습니다.(zsh가 이를 기다리고 있으며 ksh93에 알릴 수 있습니다 wait
).
최신 버전(작성 당시 4.4.12)에도 bash
여전히 다음과 같은 몇 가지 버그가 있습니다.
$ bash -c 'eval cat <(echo test)'
test # OK but:
$ bash -c 'eval "echo foo;cat" <(echo test)'
foo
cat: /dev/fd/63: No such file or directory
$ bash -c 'eval f=<(echo test) "; cat \$f"'
cat: /dev/fd/63: No such file or directory
일부는 여전히 다음과 같은 파이프에 의해 트리거됩니다.
$ cat file
echo "$1"
cat "$1"
$ bash -c 'source ./file <(echo test)'
/dev/fd/63
test # OK but:
$ cat file2
echo "$1" | wc -c
cat "$1"
$ bash -c 'source ./file2 <(echo test)'
11
cat: /dev/fd/63: No such file or directory
1 파이프가 존재하면 bash는 파일 설명자를 닫습니다. 더 짧은 재생기:
$ bash -c 'f() { :; cat "$1"; }; f <(echo OK)'
OK
$ bash -c 'f() { :|:; cat "$1"; }; f <(echo test)'
cat: /dev/fd/63: No such file or directory