파이프가 뒤따르는 중첩된 프로세스 대체: "잘못된 파일 설명자"

파이프가 뒤따르는 중첩된 프로세스 대체: "잘못된 파일 설명자"

혼란스러운 오류가 발생했는데 더 잘 이해하고 싶습니다. 이 문제는 "래퍼" 셸 함수(아래 설명)의 존재를 필요로 하는 것으로 보이므로, 나의 즉각적인 관심은 오류를 제거하기 위해 그러한 셸 함수를 수정하는 방법을 찾는 것입니다. (포스트 말미에 내 문제에 대해 좀 더 구체적으로 설명했습니다.)

이 오류를 재현하기 위해 제가 생각해낸 가장 간단한 코드는 다음 스크립트에 나와 있습니다. (대본은 확실히 인위적이고 어리석지만, 처음 오류가 발생하는 현실은 이와 같은 데모에 비해 너무 복잡합니다.)

# create an input file
cat <<EOF > demo.txt
a
b
c
EOF

# create a "wrapper shell function" for /usr/bin/join
my_join_fn () {
  /usr/bin/join "$@"
}
cat <(my_join_fn  <(cat demo.txt) <(cat demo.txt))
cat <(my_join_fn  <(cat demo.txt) <(cat demo.txt)) | head -1

# create a "wrapper shell function" for /usr/local/bin/gjoin, a port of
# GNU's join function for OS X
my_gjoin_fn () {
  /usr/local/bin/gjoin "$@"
}
cat <(my_gjoin_fn <(cat demo.txt) <(cat demo.txt))
cat <(my_gjoin_fn <(cat demo.txt) <(cat demo.txt)) | head -1

# show the version of zsh
$SHELL --version

누군가 이 스크립트를 소스로 사용하면( zsh) 성공적으로 종료되고 다음과 같은(올바른) 출력이 생성됩니다.

% source demo.sh
a
b
c
a
a
b
c
a
zsh 5.0.2 (x86_64-apple-darwin11.4.2)

하지만 나중에 다시 실행하면명령줄에서 직접, 로 끝나는 스크립트의 두 줄 중 하나에서 오류가 | head -1발생합니다 bad file descriptor.

% cat <(my_join_fn  <(cat demo.txt) <(cat demo.txt)) | head -1
join: /dev/fd/11: Bad file descriptor
% cat <(my_gjoin_fn <(cat demo.txt) <(cat demo.txt)) | head -1
/usr/local/bin/gjoin: /dev/fd/11: Bad file descriptor

이는 명령줄에서 직접 실행할 때 오류가 발생하는 스크립트의 유일한 두 줄입니다.

출력 결과에서 볼 수 있듯이 $SHELL --version위에 표시된 결과는 OS X에서 얻은 것이지만 Linux에서도 비슷한 테스트를 수행했을 때 비슷한 결과를 얻었습니다.

% cat <(my_join_fn  <(cat demo.txt) <(cat demo.txt)) | head -1
/usr/bin/join: /proc/self/fd/11: No such file or directory
% $SHELL --version
zsh 4.3.10 (x86_64-unknown-linux-gnu)

bash(OS X 또는 Linux)에서는 이 오류를 재현 할 수 없습니다 . zsh이로 인해 이 버그가 .

그러므로 해결책을 찾고 싶습니다. 내 질문은 다음과 같습니다

my_gjoin_fn이 오류를 방지하려면 래핑 셸 함수의 정의를 어떻게 수정해야 합니까 ?

(실제 대응은 my_gjoin_fn플래그가 호출에 포함된다는 점을 제외하면 위에 제공된 것과 거의 동일 합니다 gjoin.

my_gjoin_fn () {
  /usr/local/bin/gjoin -t$'\t' "$@"
}

이것을 사용하여 쉘 함수를 래핑합니다.항상, 그래서 저는 그것을 "저장"하고 싶었습니다. )

편집하다:

| head -1| head -10명령 끝을 , | cat, 등 으로 바꿔도 | tee /dev/null오류가 여전히 존재합니다. | :예를 들어:

% cat <(my_join_fn  <(cat demo.txt) <(cat demo.txt)) | cat
/usr/bin/join: /proc/self/fd/11: No such file or directory

또한 ls -l /proc/self/fdmsw에서 제안한 대로 추가하면 다음과 같은 결과가 생성됩니다.

% cat <(ls -l /proc/self/fd; my_join_fn  <(cat demo.txt) <(cat demo.txt)) | cat
total 0
lrwx------ 1 jones jones 64 Aug 21 12:29 0 -> /dev/pts/18
l-wx------ 1 jones jones 64 Aug 21 12:29 1 -> pipe:[312539706]
lrwx------ 1 jones jones 64 Aug 21 12:29 2 -> /dev/pts/18
lr-x------ 1 jones jones 64 Aug 21 12:29 3 -> /proc/23849/fd
/usr/bin/join: /proc/self/fd/11: No such file or directory

...그건 아무 의미도 없어많지만 다른 사람들에게 더 많은 정보를 제공할 수 있습니다. FWIW, ls -l /proc/self/fd내가 들어가든 zsh나가든 bash, 또한 FWIW, ls -l /proc/self/fd혼자 실행할 때의 출력은 다음과 같습니다 .

% ls -l /proc/self/fd
total 0
lrwx------ 1 jones jones 64 Aug 21 12:32 0 -> /dev/pts/18
lrwx------ 1 jones jones 64 Aug 21 12:32 1 -> /dev/pts/18
lrwx------ 1 jones jones 64 Aug 21 12:32 2 -> /dev/pts/18
lr-x------ 1 jones jones 64 Aug 21 12:32 3 -> /proc/5246/fd

답변1

를 사용하여 동작을 재현할 수 있었습니다 zsh 4.3.10 (i686-pc-linux-gnu).

% cat <(funjoin  <(cat demo) <(cat demo)) | head -1 
join: /proc/self/fd/11: No such file or directory

나는 매뉴얼을 파헤쳐 이 문제에 가장 가까운 것이 Process Substitution in man zshexpnand MULTIOS in Chapters 라는 것을 발견했습니다 man zshmisc.

두 장 모두 명령 부분에 중괄호를 넣는 것과 관련된 해결 방법을 제안합니다.

나는 노력했다

% { cat <(funjoin  <(cat demo) <(cat demo)) } | head -1
1

효과가있다.

{ }zsh의 의미를 잘 이해할 수 없습니다 . 매뉴얼에서는 간단히 명령어 목록으로 설명합니다. 나는 이 MULTIOS가 무엇을 하는지 완전히 이해하지 못합니다. 활성화하거나 비활성화해도 별 차이가 없는 것 같습니다.

함수 본문 내부를 포함하여 다른 위치에 중괄호를 배치하려고 시도했지만 funjoin올바르게 작동하는 유일한 장소는 외부입니다 cat.

답변2

Linux에서는 zsh_5.0.0-2ubuntu3_amd64.deb 아래에서 이를 재현할 수 없었지만 /proc/self/fd/11상당히 높은 숫자인 것 같습니다. 그냥 실패할까요 head -1? 어때요 head -10? 출력인가

cat <(ls -l /proc/self/fd ; my_join_fn  <(cat demo.txt) <(cat demo.txt)) | head -1

조명이 나오나요?

관련 정보