Цикл «while read» скрипта Bash приводит к ошибке «broken pipe» при запуске с помощью GNU Parallel

Цикл «while read» скрипта Bash приводит к ошибке «broken pipe» при запуске с помощью GNU Parallel

Согласно списку рассылки GNU Parallel, это не проблема, связанная с GNU Parallel. Мне предложили разместить мою проблему здесь.

Ошибка, которую я получаю, это ошибка "broken pipe", но я чувствую, что должен сначала объяснить контекст моей проблемы и то, что вызывает эту ошибку. Это происходит при попытке использовать любой скрипт bash, содержащий цикл 'while read' в GNU Parallel.

У меня есть простой bash-скрипт вроде этого:

#!/bin/bash
# linkcheck.sh

while read domain
do
host "$domain"
done

Предположим, что я хочу передать по конвейеру большой список (например, 250 МБ).

cat urllist | ./linkcheck.sh

Выполнение команды host на URL размером 250 МБ довольно медленное. Чтобы ускорить процесс, я хочу разбить ввод на части перед его передачей по конвейеру, а затем запустить несколько заданий параллельно. GNU Parallel способен на это.

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

{} заменяется содержимым urllist построчно. Предположим, что настройки моей системы по умолчанию способны запускать 500 заданий на экземпляр parallel. Чтобы обойти это ограничение, мы можем распараллелить сам Parallel:

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

Это запустит около 5000 заданий. Это также, к сожалению, вызовет ошибку "сломанная труба"(часто задаваемые вопросы по bash). Тем не менее, скрипт начинает работать, если я уберу цикл while read и буду брать входные данные непосредственно из того, что подается в {}, например,

#!/bin/bash
# linkchecker.sh

domain="$1"
host "$1"

Почему это не будет работать с циклом while read? Безопасно ли просто отключить сигнал SIGPIPE, чтобы остановить сообщение "сломанная труба", или это будет иметь побочные эффекты, такие как повреждение данных?

Спасибо за прочтение.

решение1

Итак, сделал

cat urllist | параллельный --pipe -j0 параллельный ./linkcheck.sh {}

работают правильно? Я думаю, что часть вашей проблемы может быть в том, что вы пропустили второй --pipe, как в

cat urllist | параллельный -j10 --pipe параллельный -j0--трубка./linkcheck.sh {}

 


Кстати, тебе никогда не нужно говорить

котодин_файл|какая-то_команда

Вы всегда можете изменить это на

какая-то_команда<один_файл

в результате получается на один процесс меньше (и на один канал меньше). (Это может быть уместно/необходимо использовать, catкогда у вас есть несколько входных файлов.)

решение2

Мне кажется, что ошибка может возникать из-за плохого состояния гонки из-за окна между разветвлением дочернего процесса для запуска другой копии linkcheck.sh, пока канал все еще открыт, и когда дочерний процесс фактически пытается прочитать. В этом окне другая копия прочитала EOF, и канал закрылся.

Связанный контент