El bucle 'mientras se lee' del script Bash provoca un error de 'tubería rota' cuando se ejecuta con GNU Parallel

El bucle 'mientras se lee' del script Bash provoca un error de 'tubería rota' cuando se ejecuta con GNU Parallel

Según la lista de correo de GNU Parallel, este no es un problema específico de GNU Parallel. Me sugirieron que publicara mi problema aquí.

El error que recibo es un error de "tubería rota", pero creo que debo explicar primero el contexto de mi problema y la causa de este error. Ocurre al intentar utilizar cualquier script bash que contenga un bucle "mientras se lee" en GNU Parallel.

Tengo un script bash básico como este:

#!/bin/bash
# linkcheck.sh

while read domain
do
host "$domain"
done

Supongamos que quiero canalizar una lista grande (digamos 250 MB).

cat urllist | ./linkcheck.sh

Ejecutar el comando host en 250 MB de URL es bastante lento. Para acelerar las cosas, quiero dividir la entrada en fragmentos antes de canalizarla y luego ejecutar varios trabajos en paralelo. GNU Parallel es capaz de hacer esto.

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

{} se sustituye por el contenido de la lista de direcciones línea por línea. Supongamos que la configuración predeterminada de mi sistema es capaz de ejecutar 500 trabajos por instancia de paralelo. Para sortear esta limitación podemos paralelizar el propio Parallel:

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

Esto ejecutará 5000 trabajos. Lamentablemente, también provocará el error "tubería rota".(Preguntas frecuentes sobre bash). Sin embargo, el script comienza a funcionar si elimino el ciclo while de lectura y tomo información directamente de lo que se introduce en {}, por ejemplo,

#!/bin/bash
# linkchecker.sh

domain="$1"
host "$1"

¿Por qué no funciona con un bucle de lectura while? ¿Es seguro simplemente apagar la señal SIGPIPE para detener el mensaje de "tubería rota", o eso tendrá efectos secundarios como corrupción de datos?

Gracias por leer.

Respuesta1

Así lo hizo

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

funciona correctamente? Creo que parte de tu problema puede ser que omitiste el segundo --pipe, como en

lista de URL de gatos | paralelo -j10 --tubo paralelo -j0--tubo./linkcheck.sh {}

 


Por cierto, nunca necesitas decir

gatoun_archivo|algún_comando

Siempre puedes cambiar esto a

algún_comando<un_archivo

lo que resulta en un proceso menos (y una tubería menos). (Puede ser apropiado/necesario usarlo catcuando tenga varios archivos de entrada).

Respuesta2

Me parece que el error puede surgir debido a una mala condición de carrera debido a la ventana entre la bifurcación de un niño para ejecutar otra copia de linkcheck.sh mientras la tubería aún está abierta y cuando el niño realmente intenta leer. En esa ventana, otra copia leyó EOF y la tubería se cerró.

información relacionada