Estou executando o seguinte comando em um sistema ubuntu:
dd if=/dev/random of=rand bs=1K count=2
No entanto, toda vez que eu o executo, acabo com um arquivo de tamanho diferente. Por que é isso? Como posso gerar um arquivo de um determinado tamanho preenchido com dados aleatórios?
/dev/random
bloqueará se não houver entropia suficiente disponível para gerar o número de dígitos desejado. simplesmente leva tempo para reunir essa quantidade de "aleatoriedade" aleatória psuedo de alta qualidade ... Use/dev/urandom
um valor "aleatório" menos aleatório ou verifique seu pool de entropia (em um loop e aguarde conforme necessário) ...iflag=fullblock
Respostas:
Você está observando uma combinação do comportamento peculiar de
dd
com o comportamento peculiar do Linux/dev/random
. Ambos, a propósito, raramente são a ferramenta certa para o trabalho.O Linux
/dev/random
retorna dados com moderação. É baseado na suposição de que a entropia no gerador de números pseudo-aleatórios é extinta a uma taxa muito rápida. Como a coleta de nova entropia é lenta,/dev/random
normalmente renuncia apenas a alguns bytes de cada vez.dd
é um programa antigo e irritadiço, inicialmente destinado a operar em dispositivos de fita. Quando você diz para ler um bloco de 1kB, ele tenta ler um bloco. Se a leitura retornar menos de 1024 bytes, é difícil, é tudo o que você obtém. Entãodd if=/dev/random bs=1K count=2
faz duasread(2)
ligações. Como está lendo/dev/random
, as duasread
chamadas normalmente retornam apenas alguns bytes, em número variável, dependendo da entropia disponível. Consulte também Quando o dd é adequado para copiar dados? (ou, quando são lidos () e gravados () parciais)A menos que você esteja projetando um instalador ou clonador do sistema operacional, nunca deve usar o
/dev/random
Linux sempre/dev/urandom
. Aurandom
página de manual é um pouco enganadora;/dev/urandom
é de fato adequado para criptografia, mesmo para gerar chaves de vida longa. A única restrição/dev/urandom
é que ele deve ser fornecido com entropia suficiente; As distribuições Linux normalmente salvam a entropia entre as reinicializações, portanto, o único momento em que você pode não ter entropia suficiente é em uma nova instalação. A entropia não se esgota em termos práticos. Para obter mais informações, leia Um rand de / dev / urandom é seguro para uma chave de login? e Alimentação / dev / pool de entropia aleatória? .A maioria dos usos de
dd
é melhor expressa com ferramentas comohead
outail
. Se você quiser 2kB de bytes aleatórios, executeCom os kernels Linux mais antigos, você pode se safar
porque
/dev/urandom
felizmente retornou quantos bytes foram solicitados. Mas isso não é mais verdade desde o kernel 3.16, agora é limitado a 32 MB .Em geral, quando você precisa usar
dd
para extrair um número fixo de bytes e sua entrada não é proveniente de um arquivo regular ou dispositivo de bloco, você precisa ler byte a byte:dd bs=1 count=2048
.fonte
/dev/urandom
retorna 32m porread()
.dd if=/dev/urandom ibs=1k obs=1k | dd bs=1k count=2
Em
man 4 random
uma caixa RHEL 5:Eu recebo arquivos de tamanho 213 bytes nessa máquina. Voltar ao man 4 random:
Eu recebo 2048 bytes de cada chamada de
dd if=/dev/urandom of=rand bs=1K count=2
Concluo que a diferença se deve à quantidade de entropia que sua máquina gera entre invocações de
dd if=/dev/random ...
fonte
dd if=/dev/random bs=1K count=2
parar quando a piscina de entropia é aparentemente drenada. Nos documentos, ele deve bloquear até que haja mais entropia, paradd
que o arquivo seja gravado lentamente, em vez de apenas despejar o pool atual e sair.read(fd, mybuf, 1024)
um FD de bloqueio, ele retorna assim que o dispositivo subjacente retorna alguns dados. Se houver 1024 bytes para serem lidos, isso retornará. Se houver apenas 201 bytes, ele retornará 201. Se houver 0 bytes disponíveis, ele bloqueará até que pelo menos um byte seja disponibilizado e retorne-os.Por que
dd
soltar dados? ... Gilles fez esta pergunta interessante sobredd
:quando o dd é adequado para copiar dados? (ou, quando são lidos () e escritos () parciais)
Aqui está um trecho dessa pergunta:
* ... não é difícil colocar dd em falha; por exemplo, tente este código: **
yes | dd of=out bs=1024k count=10
e verifique o tamanho do arquivo de saída (é provável que esteja bem abaixo de 10 MB).
Além do meu comentário (no final da sua pergunta), algo assim é muito interessante de assistir ... Ele captura seus bytes no arquivo
$trnd
. Escolhi semi-arbitrariamente bs = 8Mova o mouse e observe-o acelerar.
Com o meu computador ocioso (AFK e nenhuma atividade de rede) e depois de esgotar o pool de entropia, demorou 2 horas e 12 minutos para coletar apenas 1192 bytes, momento em que o cancelei.
Então, comigo movendo o mouse continuamente, foram necessários 1 minuto e 15 segundos relativamente mais curtos para coletar o mesmo número de bytes.
Isso mostra claramente que a coleta de entropia não se baseia na velocidade da CPU, mas sim em eventos aleatórios , e que meu sistema Ubuntu usa o mouse como um dos fatores aleatórios significativos .
fonte
dd
foi projetado para bloqueio - geralmente é a melhor ferramenta à sua disposição para leitura de entradas de tamanho variável, se você precisar fazer isso imediatamente, porquedd
não armazenará as leituras atuais em algum futurowrite()
(a menos que você a configure explicitamente dessa maneira com mais obs do que ibs) , mas faráwrite()
tudo o que ler assim queread()
for (e, opcionalmente, o processará) .Aqui estão algumas definições importantes :
ibs=
expr
expr
obs=
expr
expr
bs=
expr
expr
bytes, substituindoibs=
eobs=
. Se nenhuma conversão diferente desync
,noerror
enotrunc
for especificada, cada bloco de entrada deve ser copiado para a saída como um único bloco sem agregar blocos curtos.Então você vê, quando
ibs
eobs
é definido em conjunto, comobs
entãoibs
tem precedência - mas, caso contrário, se você é específico, podeobs
oucbs
não.Aqui está um exemplo em que
ibs
é mais importante. Você pode fazer algo assim se quiser acompanhar quanto tempo a/dev/random
piscina enche ...Enquanto
if=
's meta é legível em tudo, que vai sempre resultar no mesmo arquivo de saída de tamanho, porquedd
vaisync
hronize blocos leia-in on nulos. Em outras palavras, sedd
read()
s para um bloco de entrada de$((size=10))
$((count=5))
vezes e oread()
arquivo retornar 2 bytes, 8 bytes, 12 bytes, 2 bytes e 4 bytes,dd
gravarão em seu arquivo externo algo como... porque
dd
, por padrão, não demora. Portanto, se você precisar acompanhar o fluxo e delimitar as gravações de algum outro processo,dd
é a ferramenta para você.Se você estiver gravando apenas uma quantidade de dados em um arquivo regular, ao contrário de outras declarações feitas aqui, também poderá usá
dd
-lo - e com bastante facilidade - mas precisará de mais de um e um fator de bloqueio confiável .Por exemplo, se você fez:
... o primeiro
dd
armazenaria em buffer quantosibs="$size"
blocos de entrada fossem necessários para preencher pelo menos umobs="${size}x$block_factor"
bloco de saída para cadawrite()
canal no tubo entre ele e o segundodd
. Isso significa que o segundodd
pode limitar a saída de forma confiável,count="$lmt"
porque todos oswrite()
s que o primeiro faz corresponderão ao seu tamanho de bloco de E / S - independentemente de quantosread()
s o primeirodd
deve fazer para fazê-lo.E que é assim que você pode usar
dd
para tubos confiável ler ou outros tipos de arquivos especiais - com apenas um pouco de matemática.fonte