Concaténer rapidement plusieurs fichiers sur Linux
j'utilise Python multiprocessing pour générer un fichier de sortie temporaire par processus. Ils peuvent être plusieurs GBs dans la taille et je fais plusieurs dizaines de ceux-ci. Ces fichiers temporaires doivent être concated pour former la sortie désirée et c'est l'étape qui s'avère être un goulot d'étranglement (et un parallélisme killer). Existe-t-il un outil Linux qui créera le fichier concassé en modifiant les méta-données du système de fichiers et qui ne copiera pas le contenu ? Tant qu'il fonctionne sur N'importe quel système Linux qui serait acceptable pour moi. Mais une solution spécifique au système de fichiers ne sera pas d'une grande aide.
Je ne suis pas formé en OS ou CS, mais en théorie, il semble qu'il devrait être possible de créer une nouvelle inode et de copier sur la structure de pointeur d'inode à partir de l'inode des fichiers que je veux copier, puis de débloquer ces inodes. Est-il un utilitaire qui va le faire ? Étant donné la surabondance d'Utilités unix bien pensées, je m'y attendais, mais je n'ai rien trouvé. D'où ma question sur SI. Le système de fichiers est sur un périphérique de bloc, un disque dur en fait, au cas où cette information importe. Je n'ai pas la confiance nécessaire pour écrire ceci moi-même, car je n'ai jamais fait de programmation au niveau des systèmes avant, donc n'importe quel pointeur (vers des extraits de code C/Python) sera très utile.
6 réponses
même s'il y avait un tel outil, cela ne pouvait fonctionner que si les fichiers sauf le dernier ont la garantie d'avoir une taille qui est un multiple du système de fichiers du bloc taille.
si vous contrôlez comment les données sont écrites dans les fichiers temporaires, et vous savoir comment grand chacun sera, vous pouvez à la place faire la suivante
-
avant de lancer le multiprocessing, créer le fichier de sortie final, et grandir pour la taille finale par
fseek()
ing à la fin, cela va créer une fichier fragmenté . -
Commencer le traitement multiple, en remettant à chaque processus de la FD et le décalage dans ses tranche particulière du dossier.
de cette façon, les processus rempliront en collaboration le fichier de Sortie unique, on n'a plus besoin de les suivre ensemble plus tard.
MODIFIER
Si vous ne pouvez pas prédire la taille des fichiers individuels, mais le consommateur de la
le fichier final peut fonctionner avec l'entrée séquentielle (par opposition à l'accès aléatoire), vous pouvez
aliments pour animaux cat tmpfile1 .. tmpfileN
destinés au consommateur, présentés soit en récipients d'une contenance au moins égale à 151950920"
cat tmpfile1 ... tmpfileN | consumer
ou par l'intermédiaire de tubes nommés (en utilisant le procédé de substitution de bash):
consumer <(cat tmpfile1 ... tmpfileN)
Vous indiquez que vous ne savez pas à l'avance la taille de chaque fichier temporaire. Avec ceci à l'esprit, je pense que votre meilleure chance est d'écrire un système de fichiers FUSE qui présenterait les morceaux comme un seul grand fichier, tout en les gardant comme des fichiers individuels sur le système de fichiers sous-jacent.
dans cette solution, vos applications de production et de consommation restent inchangées. Les producteurs écrivent un tas de fichiers que la couche de fusible fait apparaître en un seul fichier. Ce fichier virtuel est ensuite présenté au consommateur.
FUSE a des fixations pour un tas de langues, y compris Python . Si vous regardez quelques exemples ici ou ici (ceux-ci sont pour des reliures différentes), cela nécessite étonnamment peu de code.
Je ne pense pas, inode peut être aligné, donc il ne peut être possible que si vous êtes ok de laisser quelques zéros (ou octets inconnus) entre le pied de page d'un fichier et l'en-tête d'un autre fichier.
au lieu de concaténer ces fichiers, j'aimerais suggérer de re-concevoir l'outil d'analyse pour prendre en charge le sourcing à partir de plusieurs fichiers. Prenez les fichiers journaux par exemple, de nombreux analyseurs de journaux prennent en charge la lecture des fichiers journaux pendant une journée.
MODIFIER
@san: comme vous dites le code en usage, vous ne pouvez pas le contrôler, bien vous pouvez concaténer les fichiers séparés à la volée en utilisant des pipes nommées:
$ mkfifo /tmp/cat
$ cat file1 file2 ... >/tmp/cat &
$ user_program /tmp/cat
...
$ rm /tmp/cat
Pour les 4 fichiers; xaa, xab, xac, xad un rapide concatention en bash (en tant que root):
losetup -v -f xaa; losetup -v -f xab; losetup -v -f xac; losetup -v -f xad
(supposons que loop0, loop1, loop2, loop3 sont les noms des nouveaux fichiers de périphériques.)
Put http://pastebin.com/PtEDQH7G dans un fichier de script" join_us". Ensuite, vous pouvez l'utiliser comme ceci:
./join_us /dev/loop{0..3}
alors (si ce gros fichier est un film) vous pouvez donner sa propriété à un utilisateur normal (chown itsme /dev/mapper/joint) et alors il/elle peut jouer via: mplayer /dev/mapper/joint
Le nettoyage après ceux-ci (en tant que root):
dmsetup remove joined; losetup -d /dev/loop[0123]
non, il N'existe aucun outil de ce type ou syscall.
, Vous pouvez étudier s'il est possible pour chaque processus d'écrire directement dans le fichier final. Dire que le processus 1 écrit les octets 0-X, le processus 2 écrit X-2X et ainsi de suite.
une alternative potentielle est de cataloguer tous vos fichiers temp dans un tube nommé, puis d'utiliser ce tube nommé comme entrée dans votre programme à entrée unique. Tant que votre programme à une seule entrée ne fait que lire l'entrée séquentiellement et ne cherche pas.