45 votes

Est-il sûr de diriger la sortie de plusieurs processus parallèles vers un seul fichier en utilisant >> ?

Je récupère des données sur le web et j'ai plusieurs processus de mon scraper qui tournent en parallèle.

Je veux que la sortie de chacun de ces processus aboutisse dans le même fichier. Tant que les lignes de texte restent intactes et ne sont pas mélangées, l'ordre des lignes n'a pas d'importance. Sous UNIX, puis-je simplement diriger la sortie de chaque processus vers le même fichier à l'aide de l'opérateur >> ?

32voto

Mark Byers Points 318575

Non. Il n'est pas garanti que les lignes restent intactes. Elles peuvent s'entremêler.

En cherchant à partir de la réponse de Liori, j'ai trouvé cette :

Les demandes d'écriture de {PIPE_BUF} octets ou moins ne doivent pas être entrelacées avec des données provenant d'autres processus effectuant des écritures sur le même tuyau. Les écritures supérieures à {PIPE_BUF} octets peuvent avoir des données entrelacées, sur des limites arbitraires, avec des écritures effectuées par d'autres processus, que l'indicateur O_NONBLOCK des indicateurs d'état de fichier soit activé ou non.

Il n'est donc pas garanti que les lignes plus longues que {PIPE_BUF} octets restent intactes.

14voto

rainkinz Points 3419

Une chose intéressante que vous pourriez faire est d'utiliser gnu parallel : http://www.gnu.org/s/parallel/ Par exemple, si vous avez parcouru les sites en ligne (spidering) :

stackoverflow.com, stackexchange.com, fogcreek.com 

vous pourriez faire quelque chose comme ceci

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

et la sortie est mise en mémoire tampon par parallel et, grâce à l'option -k, vous est renvoyée dans l'ordre de la liste des sites ci-dessus. Un exemple réel (essentiellement copié à partir du 2ème screencast de parallel) :

 ~ $ (echo stackoverflow.com; echo stackexchange.com; echo fogcreek.com) | parallel -k ping -c 1 {}

PING stackoverflow.com (64.34.119.12): 56 data bytes

--- stackoverflow.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

Quoi qu'il en soit, je vous laisse le soin d'en juger.

8voto

liori Points 13629

En général, non.

Sous Linux, cela pourrait être possible, à condition que deux conditions soient remplies : chaque ligne est écrite en une seule opération, et la ligne n'est pas plus longue que PIPE_SIZE (généralement la même que PAGE_SIZE, habituellement 4096). Mais... Je ne compterais pas là-dessus ; ce comportement pourrait changer.

Il est préférable d'utiliser un mécanisme de journalisation réel, comme syslog.

5voto

Bolster Points 2153

Définitivement non, j'avais un script script de gestion des logs où je supposais que cela fonctionnait, et cela fonctionnait, jusqu'à ce que je le déplace sur un serveur de production sous-chargé. Ce n'était pas un bon jour... Mais en fait, on se retrouve parfois avec des lignes complètement mélangées.

Si j'essaie de capturer des données provenant de plusieurs sources, il est beaucoup plus simple (et plus facile à déboguer) d'avoir des "traces écrites" dans plusieurs fichiers et, si j'ai besoin d'un fichier journal global, de le concaténer sur la base de l'horodatage (vous utilisez des horodateurs, n'est-ce pas ?) ou, comme l'a dit Liori, de syslog.

4voto

Max E. Points 1246

Utiliser des fichiers temporaires et les concaténer. C'est le seul moyen sûr de faire ce que vous voulez, et il y aura (probablement) une perte de performance négligeable de cette façon. Si les performances sont vraiment un problème, essayez de vous assurer que votre répertoire /tmp est un système de fichiers basé sur la RAM et placez-y vos fichiers temporaires. De cette manière, les fichiers temporaires sont stockés dans la RAM plutôt que sur un disque dur, de sorte que leur lecture/écriture est quasi instantanée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X