GNU Parallel을 사용하여 실행하면 Bash 스크립트 '읽는 동안' 루프가 '깨진 파이프' 오류를 발생시킵니다.

GNU Parallel을 사용하여 실행하면 Bash 스크립트 '읽는 동안' 루프가 '깨진 파이프' 오류를 발생시킵니다.

GNU Parallel 메일링 리스트에 따르면 이는 GNU Parallel 특정 문제가 아닙니다. 그들은 내가 여기에 내 문제를 게시할 것을 제안했습니다.

제가 받고 있는 오류는 "깨진 파이프" 오류입니다. 하지만 먼저 문제의 맥락과 이 오류의 원인을 설명해야 한다고 생각합니다. GNU Parallel에서 '읽는 동안' 루프가 포함된 bash 스크립트를 사용하려고 할 때 발생합니다.

다음과 같은 기본 bash 스크립트가 있습니다.

#!/bin/bash
# linkcheck.sh

while read domain
do
host "$domain"
done

큰 목록(250MB)을 파이프로 연결하고 싶다고 가정해 보겠습니다.

cat urllist | ./linkcheck.sh

250MB 상당의 URL에 대해 호스트 명령을 실행하는 것은 다소 느립니다. 속도를 높이기 위해 입력을 파이핑하기 전에 여러 개의 덩어리로 나누고 여러 작업을 병렬로 실행하고 싶습니다. GNU Parallel은 이를 수행할 수 있습니다.

cat urllist | parallel --pipe -j0 parallel ./linkcheck.sh {}

{}는 urllist의 내용으로 한 줄씩 대체됩니다. 내 시스템 기본 설정이 병렬 인스턴스당 500개의 작업을 실행할 수 있다고 가정합니다. 이 제한을 해결하기 위해 Parallel 자체를 병렬화할 수 있습니다.

cat urllist | parallel -j10 --pipe parallel -j0 ./linkcheck.sh {}

이것은 5000'ish 작업을 실행합니다. 또한 슬프게도 "깨진 파이프" 오류가 발생합니다.(배시 FAQ). 그러나 while 읽기 루프를 제거하고 {}에 공급되는 모든 것에서 직접 입력을 받으면 스크립트가 작동하기 시작합니다. 예:

#!/bin/bash
# linkchecker.sh

domain="$1"
host "$1"

왜 while 읽기 루프에서는 작동하지 않습니까? "깨진 파이프" 메시지를 중지하기 위해 SIGPIPE 신호를 끄는 것이 안전합니까? 아니면 데이터 손상과 같은 부작용이 있습니까?

읽어 주셔서 감사합니다.

답변1

그래서 그랬데

고양이 URL 목록 | 병렬 --pipe -j0 병렬 ./linkcheck.sh {}

올바르게 작동합니까? 나는 당신의 문제의 일부가 다음 --pipe과 같이 두 번째를 생략했다는 것일 수 있다고 생각합니다.

고양이 URL 목록 | 병렬 -j10 --파이프 병렬 -j0--파이프./linkcheck.sh {}

 


그런데, 말할 필요도 없지

고양이one_file|some_command

언제든지 이것을 다음으로 변경할 수 있습니다.

some_command<one_file

결과적으로 프로세스가 하나 줄어들고 파이프도 하나 줄어듭니다. ( cat입력 파일이 여러 개인 경우 사용하는 것이 적절하거나 필요할 수 있습니다 .)

답변2

파이프가 아직 열려 있는 동안 하위에서 linkcheck.sh의 다른 복사본을 실행하도록 분기하는 것과 하위가 실제로 읽으려고 시도하는 사이의 창으로 인해 잘못된 경쟁 조건으로 인해 오류가 발생할 수 있는 것 같습니다. 해당 창에서 다른 복사본이 EOF를 읽었고 파이프가 닫혔습니다.

관련 정보