Сценарий Bash, в то время как чтение цикла вызывает ошибку «сломанный канал» при запуске с GNU Parallel

1939
Joe White

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

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

У меня есть базовый сценарий Bash, как это:

#!/bin/bash # linkcheck.sh  while read domain do host "$domain" done 

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

cat urllist | ./linkcheck.sh 

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

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

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

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

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

#!/bin/bash # linkchecker.sh  domain="$1" host "$1" 

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

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

2

2 ответа на вопрос

1
Scott

Итак, сделал

кошачий урлист | параллель --pipe -j0 параллель ./linkcheck.sh {} 

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

кошачий урлист | параллель -j10 --pipe параллель -j0 --pipe ./linkcheck.sh {} 

 


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

кот one_file | some_command 

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

some_command < one_file 

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

Благодарю. Отсутствие второго - трубы было моей проблемой. Я мог бы поклясться, что уже пробовал это, но, очевидно, нет. Joe White 11 лет назад 0
@Joe: Кроме того, если вы используете `--pipe`, я подозреваю, что` {} `не нужен / игнорируется. Scott 11 лет назад 1
0
Nicole Hamilton

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

Да, я думаю, что вы правы. Спасибо за ваш вклад. Joe White 11 лет назад 0

Похожие вопросы