Résumé: dd
est un outil grincheux qui est difficile à utiliser correctement. Ne l'utilisez pas, malgré les nombreux tutoriels qui vous le disent. dd
a une ambiance «credo unix street» qui y est attachée - mais si vous comprenez vraiment ce que vous faites, vous saurez que vous ne devriez pas le toucher avec un poteau de 10 pieds.
dd
effectue un seul appel à l' read
appel système par bloc (défini par la valeur de bs
). Il n'y a aucune garantie que l' read
appel système renvoie autant de données que la taille de mémoire tampon spécifiée. Cela a tendance à fonctionner pour les fichiers normaux et les périphériques de bloc, mais pas pour les canaux et certains périphériques de caractères. Voir Quand dd convient-il pour copier des données? (ou, quand sont read () et write () partial) pour plus d'informations. Si l' read
appel système renvoie moins d'un bloc complet, dd
transfère alors un bloc partiel. Il copie toujours le nombre spécifié de blocs, de sorte que le nombre total d'octets transférés est inférieur à celui demandé.
L'avertissement concernant une «lecture partielle» vous dit exactement ceci: l'une des lectures était partielle, donc dd
transféré un bloc incomplet. Dans le nombre de blocs, +1
signifie qu'un bloc a été lu partiellement; puisque le nombre de sorties est +0
, tous les blocs ont été écrits comme lus.
Cela n'affecte pas le caractère aléatoire des données: tous les octets qui sont dd
écrits sont des octets de lecture /dev/urandom
. Mais vous avez obtenu moins d'octets que prévu.
Linux /dev/urandom
accepte des requêtes arbitraires de grande taille (source: extract_entropy_user
in drivers/char/random.c
), il dd
est donc normalement sûr lors de la lecture. Cependant, la lecture de grandes quantités de données prend du temps. Si le processus reçoit un signal, l' read
appel système revient avant de remplir son tampon de sortie. Il s'agit d'un comportement normal et les applications sont censées appeler read
en boucle; dd
ne le fait pas, pour des raisons historiques ( dd
les origines de sombres, mais il semble avoir commencé comme un outil pour accéder aux bandes, qui ont des exigences particulières, et n'a jamais été adapté pour être un outil à usage général). Lorsque vous vérifiez la progression, cela envoie au dd
processus un signal qui interrompt la lecture. Vous avez le choix entre savoir combien d'octetsdd
copiera au total (assurez-vous de ne pas l'interrompre - pas de vérification de progression, pas de suspension), ou sachez combien d'octets dd
ont été copiés jusqu'à présent, auquel cas vous ne pouvez pas savoir combien d'octets de plus il copiera.
La version de dd
dans GNU coreutils (comme on le trouve sur Linux non embarqué et sur Cygwin) a un drapeau fullblock
qui indique dd
d'appeler read
en boucle (et idem pour write
) et donc de toujours transférer des blocs entiers. Le message d'erreur suggère que vous l'utilisiez; vous devez toujours l'utiliser (à la fois dans les drapeaux d'entrée et de sortie), sauf dans des circonstances très spéciales (principalement lors de l'accès aux bandes) - si vous l'utilisez dd
, c'est-à-dire: il existe généralement de meilleures solutions (voir ci-dessous).
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
Une autre façon possible d'être sûr de ce qui dd
va faire est de passer une taille de bloc de 1. Ensuite, vous pouvez dire combien d'octets ont été copiés à partir du nombre de blocs, mais je ne sais pas ce qui se passera si a read
est interrompu avant de lire le premier octet (ce qui n'est pas très probable dans la pratique mais peut se produire). Cependant, même si cela fonctionne, c'est très lent.
Le conseil général sur l'utilisation dd
est de ne pas utiliserdd
. Bien qu'il dd
soit souvent annoncé comme une commande de bas niveau pour accéder aux appareils, ce n'est en fait rien de tel: toute la magie se produit dans la partie du fichier de l'appareil (la /dev/…
) partie, dd
est juste un outil ordinaire avec un potentiel élevé d'utilisation abusive entraînant une perte de données . Dans la plupart des cas, il existe un moyen plus simple et plus sûr de faire ce que vous voulez, au moins sous Linux.
Par exemple, pour lire un certain nombre d'octets au début d'un fichier, il suffit d'appeler head
:
head -c 1000000m </dev/urandom >file
J'ai fait un point de repère rapide sur ma machine et n'ai observé aucune différence de performance entre dd
avec une grande taille de bloc et head
.
Si vous devez ignorer certains octets au début, dirigez-le tail
vers head
:
dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output
Si vous voulez voir la progression, appelez lsof
pour voir le décalage du fichier. Cela ne fonctionne que sur un fichier standard (le fichier de sortie de votre exemple), pas sur un périphérique de caractères.
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
Vous pouvez appeler pv
pour obtenir un rapport d'avancement (meilleur que dd
le sien), au détriment d'un élément supplémentaire dans le pipeline (en termes de performances, il est à peine perceptible).