Estoy ejecutando el siguiente comando en un sistema ubuntu:
dd if=/dev/random of=rand bs=1K count=2
Sin embargo, cada vez que lo ejecuto, termino con un archivo de un tamaño diferente. ¿Por qué es esto? ¿Cómo puedo generar un archivo de un tamaño determinado lleno de datos aleatorios?
/dev/random
se bloqueará si no hay suficiente entropía disponible para generar la cantidad de dígitos que desea. simplemente toma tiempo reunir esa cantidad de "aleatoriedad" aleatoria de psuedo de alta calidad ... O use/dev/urandom
para un valor "aleatorio" menos aleatorio, o verifique su grupo de entropía (en un bucle, y espere según sea necesario) ...iflag=fullblock
Respuestas:
Estás observando una combinación del comportamiento peculiar de
dd
con el comportamiento peculiar de Linux/dev/random
. Ambos, por cierto, rara vez son la herramienta adecuada para el trabajo.Linux
/dev/random
devuelve datos con moderación. Se basa en el supuesto de que la entropía en el generador de números pseudoaleatorios se extingue a una velocidad muy rápida. Dado que la recopilación de nueva entropía es lenta,/dev/random
generalmente solo se renuncian unos pocos bytes por vez.dd
es un programa viejo y malhumorado destinado inicialmente a funcionar en dispositivos de cinta. Cuando le dice que lea un bloque de 1kB, intenta leer un bloque. Si la lectura devuelve menos de 1024 bytes, difícil, eso es todo lo que obtienes. Entoncesdd if=/dev/random bs=1K count=2
hace dosread(2)
llamadas. Como está leyendo/dev/random
, las dosread
llamadas generalmente devuelven solo unos pocos bytes, en número variable dependiendo de la entropía disponible. Consulte también ¿ Cuándo es adecuado dd para copiar datos? (o, cuando se leen () y escriben () parcial)A menos que esté diseñando un instalador o clonador del sistema operativo, nunca debe usarlo
/dev/random
bajo Linux, siempre/dev/urandom
. Laurandom
página del manual es algo engañosa;/dev/urandom
De hecho, es adecuado para la criptografía, incluso para generar claves de larga duración. La única restricción con/dev/urandom
es que debe suministrarse con suficiente entropía; Las distribuciones de Linux normalmente guardan la entropía entre reinicios, por lo que el único momento en que podría no tener suficiente entropía es en una instalación nueva. La entropía no desaparece en términos prácticos. Para obtener más información, lea ¿Es seguro un rand de / dev / urandom para una clave de inicio de sesión? y el grupo de alimentación / dev / entropía aleatoria? .La mayoría de los usos de
dd
se expresan mejor con herramientas comohead
otail
. Si quieres 2kB de bytes aleatorios, ejecutaCon los núcleos de Linux más antiguos, podría salirse con la suya
porque
/dev/urandom
felizmente devolvió tantos bytes como se solicitó. Pero esto ya no es cierto desde el kernel 3.16, ahora está limitado a 32 MB .En general, cuando se necesita para el uso
dd
para extraer un número fijo de bytes y su entrada no proviene de un archivo normal o dispositivo de bloque, es necesario leer byte a byte:dd bs=1 count=2048
.fuente
/dev/urandom
devuelve 32m porread()
.dd if=/dev/urandom ibs=1k obs=1k | dd bs=1k count=2
Desde
man 4 random
una caja RHEL 5:Recibo archivos de 213 bytes en esa máquina. De vuelta al hombre 4 al azar:
Obtengo 2048 bytes de cada invocación de
dd if=/dev/urandom of=rand bs=1K count=2
Concluyo que la diferencia se debe a la cantidad de entropía que genera su máquina entre invocaciones de
dd if=/dev/random ...
fuente
dd if=/dev/random bs=1K count=2
detiene cuando el grupo de entropía aparentemente está drenado. Desde los documentos, debe bloquearse hasta que haya más entropía, por lodd
que escribirá el archivo lentamente, en lugar de simplemente eliminar el grupo actual y salir.read(fd, mybuf, 1024)
a un FD de bloqueo, vuelve tan pronto como el dispositivo subyacente devuelve algunos datos. Si hay 1024 bytes para ser leídos, devuelve eso. Si solo hay 201 bytes, devolverá 201. Si hay 0 bytes disponibles, se bloqueará hasta que al menos un byte esté disponible, luego lo devolverá.¿Por qué se
dd
caen los datos? ... Gilles ha planteado esta interesante pregunta sobredd
: ¿Cuándo es adecuado dd para copiar datos? (o, cuando se lee () y escribe () parcial)
Aquí hay un extracto de esa pregunta:
* ... no es difícil culpar a dd; por ejemplo, pruebe este código: **
yes | dd of=out bs=1024k count=10
y verifique el tamaño del archivo de salida (es probable que sea muy inferior a 10 MB).
Aparte de mi comentario (al final de su pregunta), algo como esto es interesante de ver ... Captura sus bytes en el archivo
$trnd
. He elegido semi-arbitrariamente bs = 8Mueve el mouse y observa cómo se acelera.
Con mi computadora inactiva (AFK y sin actividad de red), y después de agotar el grupo de entropía, me tomó 2 horas 12 minutos recolectar solo 1192 bytes, momento en el cual lo cancelé.
Luego, al mover el mouse continuamente, me tomó un tiempo relativamente más corto de 1 minuto y 15 segundos para recopilar la misma cantidad de bytes.
Esto muestra con bastante claridad que la recopilación de entropía no se basa en la velocidad de la CPU, sino que se basa en eventos aleatorios , y que mi sistema Ubuntu usa el mouse como uno de sus factores aleatorios significativos .
fuente
dd
está diseñado para bloquear: por lo general, es la mejor herramienta a su disposición para leer desde entradas de tamaño variable si lo necesita de inmediato, yadd
que no almacenará las lecturas de corriente en el futurowrite()
(a menos que lo configure de manera muy explícita de esa manera con un obs mayor que ibs) , pero, en cambiowrite()
, leerá todo lo que lea tan pronto comoread()
sea (y opcionalmente lo procesará) .Aquí hay algunas definiciones importantes :
ibs=
expr
expr
obs=
expr
expr
bs=
expr
expr
bytes, reemplazandoibs=
yobs=
. Si no se especifica otra conversión quesync
,noerror
ynotrunc
se especifica, cada bloque de entrada se copiará a la salida como un bloque único sin agregar bloques cortos.Así que ya ves, cuándo
ibs
yobs
se definen juntos comobs
entoncesibs
tiene prioridad, pero de lo contrario, si eres específico, entoncesobs
o locbs
hace.Aquí hay un ejemplo en el que
ibs
es más importante. Puede hacer algo como esto si desea realizar un seguimiento de lo pronto que se/dev/random
llenó la piscina ...Mientras
if=
's objetivo se puede leer en absoluto, que será siempre como resultado el mismo tamaño de archivo de salida, porquedd
sesync
hronize bloques de lectura en el nulos. En otras palabras, sidd
read()
s es para un bloque de entrada de$((size=10))
$((count=5))
tiempos y elread()
archivo devuelve 2 bytes, luego 8 bytes, luego 12 bytes, luego 2 bytes, luego 4 bytes,dd
escribirán en su archivo de salida algo como... porque
dd
, por defecto, no se retrasa. Entonces, si necesita realizar un seguimiento in-stream y delimitar las escrituras de algún otro proceso, estadd
es la herramienta para usted.Si solo está escribiendo cierta cantidad de datos en un archivo normal, a diferencia de otras declaraciones hechas aquí, también puede usarlo
dd
para esto, y con bastante facilidad, pero necesitará más de uno y un factor de bloqueo confiable .Por ejemplo, si hiciste:
... el primero
dd
almacenará tantosibs="$size"
bloques de entrada como sean necesarios para llenar al menos unobs="${size}x$block_factor"
bloque de salida por cadawrite()
tubería entre él y el segundodd
. Esto significa que el segundodd
puede limitar la salida de manera confiablecount="$lmt"
porque todos loswrite()
s que realiza el primero coincidirán con su tamaño de bloque de E / S, independientemente de cuántosread()
sdd
debe hacer el primero para hacerlo.Y así es como puede usar
dd
para leer de manera confiable tuberías u otros tipos de archivos especiales, con solo un poco de matemática.fuente