unix concurrency parallel-processing pipe

unix - ¿Es seguro canalizar la salida de varios procesos paralelos a un archivo utilizando>>?



concurrency parallel-processing (9)

Estoy recortando datos de la web, y tengo varios procesos de mi raspador funcionando en paralelo.

Quiero que el resultado de cada uno de estos procesos termine en el mismo archivo. Mientras las líneas de texto permanezcan intactas y no se mezclen entre sí, el orden de las líneas no importa. En UNIX, ¿puedo canalizar la salida de cada proceso al mismo archivo usando el operador >>?


Además de la idea de usar archivos temporales, también puede usar algún tipo de proceso de agregación, aunque aún deberá asegurarse de que sus escrituras sean atómicas.

Piensa en Apache2 con registro por tubería (con algo así como propagación en el otro extremo de la tubería si te sientes ambicioso). Ese es el enfoque que se necesita, con múltiples hilos / procesos que comparten un único proceso de registro.


Como se mencionó anteriormente, es bastante pirata, pero funciona bastante bien =)

( ping .com & ping stackexchange.com & ping fogcreek.com ) | cat

Lo mismo con ''>>'':

( ping .com & ping stackexchange.com & ping fogcreek.com ) >> log

y con el ejecutivo en el último guardas un proceso:

( ping .com & ping stackexchange.com & exec ping fogcreek.com ) | cat


Deberá asegurarse de escribir líneas enteras en operaciones de escritura únicas (por lo tanto, si está utilizando alguna forma de stdio, deberá configurarla para el búfer de línea durante al menos la longitud de la línea más larga que puede salir.) Como el shell usa O_APPEND para la >> redirección, todas sus escrituras se agregarán automáticamente al archivo sin más acciones de su parte.


Definitivamente no, tenía un script de administración de registros en el que asumí que funcionó, y funcionó, hasta que lo moví a un servidor de producción bajo carga. No es un buen día ... Pero básicamente terminas con líneas completamente mezcladas.

Si estoy tratando de capturar desde múltiples fuentes, es mucho más simple (y más fácil de depurar) tener una ''ruta de papel'' de varios archivos y si necesito un archivo de registro general, concatenar en función de la marca de tiempo (está usando el tiempo -stamps, ¿no?) o como dijo liori, syslog.


En general, no.

En Linux esto podría ser posible, siempre que se cumplan dos condiciones: cada línea se escribe en una operación, y la línea no es más que PIPE_SIZE (generalmente lo mismo que PAGE_SIZE, generalmente 4096). Pero ... no contaría con eso; este comportamiento puede cambiar

Es mejor usar algún tipo de mecanismo de registro real, como syslog.


En resumen, no. >> no respeta procesos múltiples.


No. No se garantiza que las líneas permanezcan intactas. Se pueden mezclar.

De la búsqueda basada en la respuesta de liori encontré this :

Las solicitudes de escritura de {PIPE_BUF} bytes o menos no se intercalarán con datos de otros procesos que realizan escrituras en el mismo conducto. Las escrituras de más de {PIPE_BUF} bytes pueden tener datos intercalados, en límites arbitrarios, con escrituras de otros procesos, ya sea que se haya establecido o no el indicador O_NONBLOCK de los indicadores de estado del archivo.

Por lo tanto, no se garantiza que las líneas más largas que {PIPE_BUF} bytes permanezcan intactas.


Una cosa posiblemente interesante que podrías hacer es usar gnu parallel: http://www.gnu.org/s/parallel/ Por ejemplo, si estuvieras filtrando los sitios:

.com, stackexchange.com, fogcreek.com

podrías hacer algo como esto

(echo .com; echo stackexchange.com; echo fogcreek.com) | parallel -k your_spider_script

y el resultado se almacena en búfer por paralelo y debido a la opción -k que se le devuelve en el orden de la lista de sitios anterior. Un ejemplo real (básicamente copiado del segundo screencast paralelo):

~ $ (echo .com; echo stackexchange.com; echo fogcreek.com) | parallel -k ping -c 1 {} PING .com (64.34.119.12): 56 data bytes --- .com ping statistics --- 1 packets transmitted, 0 packets received, 100.0% packet loss PING stackexchange.com (64.34.119.12): 56 data bytes --- stackexchange.com ping statistics --- 1 packets transmitted, 0 packets received, 100.0% packet loss PING fogcreek.com (64.34.80.170): 56 data bytes 64 bytes from 64.34.80.170: icmp_seq=0 ttl=250 time=23.961 ms --- fogcreek.com ping statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 23.961/23.961/23.961/0.000 ms

De todos modos, mmmv


Use archivos temporales y concatenelos juntos. Es la única manera segura de hacer lo que quiere hacer, y habrá (probablemente) una pérdida de rendimiento insignificante de esa manera. Si el rendimiento es realmente un problema, asegúrese de que su directorio / tmp sea un sistema de archivos basado en RAM y coloque allí sus archivos temporales. De esta manera, los archivos temporales se almacenan en la memoria RAM en lugar de en un disco duro, por lo que leerlos / escribirlos es casi instantáneo.