Bonjour,
Je suis en train d'écrire un script et le résultat n'est pas bon. J'ai trouvé où est situé le problème mais je ne comprends pas pourquoi ça coince. Et je ne sais pas comment contourner.
J'ai le code suivant:
(
cat fichier1
cat fichier2
cat fichier3
) | lzop --decompress --to-stdout | (
dd of=/dev/sdb bs=100M count=290 seek=0
dd of=/dev/null bs=100M count=25 seek=290
dd of=/dev/sdb bs=100M count=1 seek=315
dd of=/dev/null bs=100M count=709 seek=316
dd of=/dev/sdb bs=100M count=31 seek=1025
)
# --> ce qui est écrit par dd n'a pas la bonne taille.
Je peux reproduire l'erreur avec un code plus simple:
dd if=/dev/urandom of=source bs=1M count=10
cat source | dd of=dest bs=3000KB count=1
# --> 0+1 enregistrements lus
# --> 0+1 enregistrements écrits
# --> 98304 octets (98 kB) copiés, 0,000621797 s, 158 MB/s
cat source | dd of=dest bs=300KB count=1
# --> 0+1 enregistrements lus
# --> 0+1 enregistrements écrits
# --> 131072 octets (131 kB) copiés, 0,000467747 s, 280 MB/s
# autre exemple:
cat /dev/urandom | dd of=/dev/null bs=3000KB count=1
# --> ce qui donne entre 4kio et 30kio écrits suivant la machine que j'utilise.
Franchement je ne pige pas ce qui cloche.
Je n'ai jamais eu de problème avec dd. A priori c'est à cause de l'utilisation de la pipe sur l'entrée standard de dd, mais je bloque là.
# À vue de nez…
Posté par Obsidian . Évalué à 3.
Pourquoi utilises-tu trois « cat » successifs dans un bloc ? « cat » signifie « catenate » et sert justement à concaténer plusieurs fichiers. Utilise plutôt « cat fichier1 fichier2 fichier3 » et vire les parenthèses ;
Si tu lis tes données depuis l'entrée standard, il faut enlever les clauses « seek ». Tu ne relis pas, à chaque fois, le même fichier depuis le début, tu lis les données qui te parviennent les unes après les autres. Le début de ton fichier a donc déjà été « consommé » par les commandes « dd » précédentes.
[^] # Re: À vue de nez…
Posté par Obsidian . Évalué à 1.
Je retire le point numéro 2. J'ai confondu « seek » et « skip ».
[^] # Re: À vue de nez…
Posté par gremous . Évalué à 1.
Pour le point 2 j'avais bien vu que tu n'avais pas vu.
Pour le cat, c'est qu'en fait il y a des commandes entre chaque fichier. Les fichiers sont sur des DVD différents. Il faut afficher un message, attendre la validation, monter, etc.
# taille de la pipe
Posté par zecrazytux (site web personnel) . Évalué à -1.
C'est effectivement lié au pipe. en utilisant l'entrée standard sans pipe, ça marche très bien ( dd ... < source)
je suggere la lecture du man pipe(7) notamment Pipe Capacity
je pense que ça vient de ça
[^] # Re: taille de la pipe
Posté par Kerro . Évalué à 2.
Les processus qui écrivent dans un pipe déjà plein sont bloqués (sauf réglage volontaire de la part du programmeur). Cela permet de faire bosser ensemble des processus qui ne traitent pas les données à la même vitesse.
Exemples dans le man de lzop:
Il y a peu de chance que sur un gros fichier l'un des processus ne soit pas en attente.
On peut même exagérer en faisant
[^] # Re: taille de la pipe
Posté par Kerro . Évalué à 2.
Vu ma réponse plus bas, c'est bel et bien un problème de vitesse pour générer les données par rapport à celle pour les consommer.
C'est bien spécifique à dd. Je vais matter le source pour savoir si c'est un bug ou pas.
Je remarque que les anciennes versions n'ont pas l'option iflag=fullblock
# C'est dd qui merde
Posté par Kerro . Évalué à 3.
Je viens de faire le test sur plusieurs machines. Toutes des Debian ou dérivées. C'est clairement dd qui merde.
Le traitement des options bs et count semble foireux.
Exemples censés donner 3Mio:
La même chose mais qui fonctionne:
Je remarque que les informations affichées par dd sont inhabituelles.
Lorsque tout va bien:
3000+0 enregistrements lus
3000+0 enregistrements écrits
3072000 octets (3,1 MB) copiés, 1,48802 s, 2,1 MB/s
Lorsque ça ne fonctionne pas:
225+75 enregistrements lus
225+75 enregistrements écrits
2457600 octets (2,5 MB) copiés, 1,17842 s, 2,1 MB/s
[^] # Re: C'est dd qui merde
Posté par Kerro . Évalué à 4.
Ça me tracasse cette histoire :-)
J'ai trouvé ce que signifient les valeur après le signe +. Ce sont les blocs lus/écrits qui ne font pas la taille demandée.
dd est censé lire en mode bloquant, mais visiblement pas pour les pipes.
Pour contourner le problème:
cat /dev/urandom | dd of=dest bs=3000K count=1 iflag=fullblock
[^] # Re: C'est dd qui merde
Posté par gremous . Évalué à 1.
C'est effectivement ça !
J'ai lu le source. Il n'y a rien dedans pour lire de manière bloquante si fullblock n'est pas utilisé. Ni pour les pipes ni pour le reste.
Alors question: comment est-ce possible que copier un disque lent vers plus rapide ne pose pas de problème ?
Ca a toujours marché ce truc. Finalement ça n'aurait pas dû puisque les lectures ne sont pas bloquantes. Donc j'ai raté un truc.
Ou alors ça veut dire que les pipes sont par défaut non bloquantes, et que les fichiers oui ? Vu que dd ne modifie pas ces paramètres, ça se tient.
[^] # Re: C'est dd qui merde
Posté par Obsidian . Évalué à 4.
Les pipes sont bien bloquants… s'il n'y a rien à lire dedans ! Mais si on fait un appel read() dessus en passant la taille d'un buffer par exemple et qu'il y a bien des caractères disponibles mais qu'il n'y a pas le compte, alors l'appel va ressortir en renvoyant le nombre de caractères qu'il a réussi à lire.
Lorsqu'on exploite directement le disque ou un fichier, la question ne se pose pas. Les caractères sont forcément disponibles et c'est directement dd (ou n'importe quel programme à sa place) qui va aller chercher les données, par l'intermédiaire du pilote. Il n'y a qu'en cas de fin de fichier ou d'erreur que le bloc à lire peut être incomplet.
Par contre, dans le cas d'un pipe, c'est entièrement au bon vouloir du processus écrivain qui, par définition, a un comportement asynchrone et versatile.
[^] # Re: C'est dd qui merde
Posté par NeoX . Évalué à -1.
parce que la lecture lente permet d'avoir un buffer vide (bloquant) et pas un buffer plein (non bloquant dans les exemples au dessus)
ce serait l'inverse qui pourrait etre problematique, copier un disque rapide vers un disque plus lent.
mais si tu n'utilises pas les pipes comme avec un simple dd if=... of=... tu n'as aucun probleme puisque c'est dd qui se debrouille tout seul, il n'y a pas de pipe ou alors juste internes.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.