Estoy usando GNU paralelo y quiero entender: ¿cómo puedo pasar la cadena individual a cada comando paralelo?
Como ejemplo,Documentación paralela de GNUmuestra cómo mover archivos del directorio actual a otro:
ls | parallel mv {} destdir
Entonces, ¿hay alguna manera de obtener/imprimir cada archivo individualmente que se pasó al paralelo?
Caso para el procesamiento paralelo
Necesito realizar un procesamiento paralelo para verificar múltiples sitios y registrar
- código de retorno http (2xx, 4xx, 5xx)
- La URL de origen
- La URL de destino final
- el código de salida curl
Aquí está el código que hace esto:
unset return_code_array
unset destination_url_array
unset exit_code_array
while read -r return_code_var destination_url_var exit_code_var; do
destination_url_array+=("$destination_url_var")
exit_code_array+=("$exit_code_var")
return_code_array+=("$return_code_var")
done < <(printf '%s\n' "${all_valid_URLs_array[@]}" | parallel -j 20 -k 'curl --max-time 20 -sL -o /dev/null -w "%{response_code} %{url_effective} " {}; printf "%s %s\n" "$?" ')
Como resultado, tengo tres matrices que contienen el código de retorno HTTP, la URL de destino final y el estado del código de salida curl para cada línea correspondiente de las all_valid_URLs_array
entradas. Al mismo tiempo, necesito realizar algún procesamiento para cada uno destination_url_var
, como comparar si coincide con la URL de origen, pero no tengo idea de cómo obtener la cadena que se pasó a paralelos.
Actualmente, estoy ejecutando un segundo ciclo después del anterior para dicho procesamiento, pero quiero saber si es posible lograrlo.
Gracias.
Respuesta1
En su ejemplo 'curl … {}; printf "%s %s\n" "$?" '
(¿por qué el segundo %s
?) es un fragmento de código de shell entre comillas simples. En él puedes usar {}
más de una vez:
curl … {}; printf "%s %s\n" "$?" {}
Alternativamente, cree una variable y úsela tantas veces como desee. El nombre de la variable puede ser descriptivo, esto es una ventaja. Hay otra ventaja: en general, lo que se sustituye {}
puede ser una cadena larga, sustituirla muchas veces puede inflar el código parallel
que pasará a shells particulares. En mi opinión, es mejor sustituir una vez y dejar que el shell guarde la cadena y la reutilice:
source_URL={}; curl … "$source_URL"; printf "%s %s\n" "$?" "$source_URL"
En el caso de GNU, parallel
es seguro incrustarlo {}
en el código shell. Es una excepción mencionada explícitamente en esta respuesta:¡Nunca incruste {}
en el código shell!. Probablemente ya lo sepas, el comentario está dirigido al público general.
Tenga en cuenta que necesita ajustar su read
en el bucle principal, ahora tiene que leersecuatrovariables. De esta manera transferirás la URL de origen desde el interior parallel
al bucle principal donde podrás compararla destination_url_var
o hacer lo que quieras.
Aún así, en este enfoque "lo que quieras" no está paralelizado.
Si captura la salida de curl
variables separadas dentro del código de Shell ejecutado parallel
(en lugar de simplemente imprimirlo para capturarlo fuera de parallel
), entonces podrá hacer una comparación (o lo que quiera)allá, en paralelo. Y por ejemploprintf
condicionalmente. Depende de usted dónde implementar la lógica deseada, siempre y cuando el interior parallel
genere resultados en la forma esperada por el exterior read
.
El código shell pasado parallel
aún debe estar entre comillas simples. A medida que crezca, es posible que necesites utilizar (incrustar) comillas simples en este mismo código; entonces las citas se volverán algo complicadas y menos legibles. En tal situación, considere mover el código a un script separado donde pueda citarlo de forma independiente. Lo invocarás desde el script principal de esta manera:
while read … ; done < <( … | parallel -j 20 -k 'path/to/separate_script {}' )
Dentro de la separate_script
cadena sustituida {}
estará disponible como $1
(no olvidecomillas dobles).