O loop 'while read' do script Bash causa erro de 'tubo quebrado' quando executado com GNU Parallel

O loop 'while read' do script Bash causa erro de 'tubo quebrado' quando executado com GNU Parallel

De acordo com a lista de discussão do GNU Parallel, este não é um problema específico do GNU Parallel. Eles sugeriram que eu postasse meu problema aqui.

O erro que estou recebendo é um erro de "tubo quebrado", mas sinto que devo primeiro explicar o contexto do meu problema e o que causa esse erro. Isso acontece ao tentar usar qualquer script bash contendo um loop 'while read' no GNU Parallel.

Eu tenho um script bash básico como este:

#!/bin/bash
# linkcheck.sh

while read domain
do
host "$domain"
done

Suponha que eu queira criar uma lista grande (digamos, 250 MB).

cat urllist | ./linkcheck.sh

Executar o comando host em URLs de 250 MB é bastante lento. Para acelerar as coisas, quero dividir a entrada em partes antes de canalizá-la e, em seguida, executar vários trabalhos em paralelo. GNU Parallel é capaz de fazer isso.

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

{} é substituído pelo conteúdo de urllist linha por linha. Suponha que a configuração padrão do meu sistema seja capaz de executar 500 trabalhos por instância paralela. Para contornar essa limitação, podemos paralelizar o próprio Parallel:

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

Isso executará 5.000 empregos. Infelizmente, também causará o erro "tubo quebrado"(perguntas frequentes sobre bash). No entanto, o script começa a funcionar se eu remover o loop while read e receber a entrada diretamente de tudo o que é inserido em {}, por exemplo,

#!/bin/bash
# linkchecker.sh

domain="$1"
host "$1"

Por que não funcionará com um loop while read? É seguro simplesmente desligar o sinal SIGPIPE para interromper a mensagem de "tubo quebrado" ou isso terá efeitos colaterais, como corrupção de dados?

Obrigado por ler.

Responder1

Assim o fez

lista de URLs de gatos | paralelo --pipe -j0 paralelo ./linkcheck.sh {}

funciona corretamente? Acredito que parte do seu problema pode ser que você deixou de fora o segundo --pipe, como em

lista de URLs de gatos | paralelo -j10 --pipe paralelo -j0--cano./linkcheck.sh {}

 


Aliás, você nunca precisa dizer

gatoarquivo_um|algum_comando

Você sempre pode mudar isso para

algum_comando<arquivo_um

resultando em um processo a menos (e um tubo a menos). (Pode ser apropriado/necessário usar catquando você tiver vários arquivos de entrada.)

Responder2

Parece-me que o erro pode estar surgindo devido a uma condição de corrida ruim devido à janela entre bifurcar um filho para executar outra cópia de linkcheck.sh enquanto o canal ainda está aberto e quando o filho realmente tenta ler. Nessa janela, outra cópia leu EOF e o canal foi fechado.

informação relacionada