Resumo: dd é uma ferramenta irritada que é difícil de usar corretamente. Não o use, apesar dos inúmeros tutoriais que dizem isso. dd tem uma vibe de "unix street cred" ligada a ele - mas se você realmente entender o que está fazendo, saberá que não deve tocá-lo com um poste de 10 pés.
dd faz uma única chamada para a chamada de sistema read por bloco (definida pelo valor de bs ). Não há garantia de que a chamada do sistema read retorne tantos dados quanto o tamanho do buffer especificado. Isso tende a funcionar para arquivos regulares e dispositivos de bloco, mas não para pipes e alguns dispositivos de caracteres. Consulte Quando dd é adequado para copiar dados? (ou, quando são ler () e escrever () parcial) para mais informações. Se a chamada do sistema read retornar menos de um bloco inteiro, então dd transfere um bloqueio parcial. Ele ainda copia o número especificado de blocos, portanto, a quantidade total de bytes transferidos é menor que o solicitado.
O aviso sobre uma "leitura parcial" diz exatamente o seguinte: uma das leituras foi parcial, portanto dd transferiu um bloco incompleto. Na contagem de blocos, +1 significa que um bloco foi lido parcialmente; já que a contagem de saída é +0 , todos os blocos foram escritos como lidos.
Isso não afeta a aleatoriedade dos dados: todos os bytes que dd escrevem são bytes lidos de /dev/urandom . Mas você tem menos bytes do que o esperado.
O /dev/urandom do Linux acomoda solicitações grandes e arbitrárias (fonte: extract_entropy_user em drivers/char/random.c ), portanto dd é normalmente seguro ao ler a partir dele. No entanto, a leitura de grandes quantidades de dados leva tempo. Se o processo receber um sinal, a chamada do sistema read retorna antes de preencher seu buffer de saída. Esse é um comportamento normal e os aplicativos devem chamar read em um loop; dd não faz isso, por razões históricas (as origens de dd são obscuras, mas parece ter começado como uma ferramenta para acessar as fitas, que têm requisitos peculiares, e nunca foi adaptada para ser uma solução geral. ferramenta de finalidade). Quando você verifica o progresso, isso envia o processo dd a um sinal que interrompe a leitura. Você tem a opção de saber quantos bytes dd irá copiar no total (certifique-se de não interrompê-lo - nenhuma verificação de progresso, nenhuma suspensão) ou saber quantos bytes dd copiou até o momento. muitos bytes que serão copiados.
A versão de dd em GNU coreutils (conforme encontrado em Linux não embarcado e no Cygwin) tem um sinalizador fullblock que informa dd para chamar read em um loop (e idem para write ) e, portanto, sempre transfere blocos inteiros. A mensagem de erro sugere que você a use; você deve sempre usá-lo (em sinalizadores de entrada e saída), exceto em circunstâncias muito especiais (principalmente ao acessar fitas) - se você usa dd , isto é: geralmente há soluções melhores (veja abaixo).
dd if=/dev/urandom iflag=fullblock oflag=fullblock of=file bs=1M count=1000000
Outra maneira possível de ter certeza do que dd fará é passar um tamanho de bloco igual a 1. Então você pode informar quantos bytes foram copiados da contagem de blocos, embora eu não tenha certeza do que acontecerá se um read é interrompido antes de ler o primeiro byte (o que não é muito provável na prática, mas pode acontecer). No entanto, mesmo que funcione, isso é muito lento.
O conselho geral sobre o uso de dd é não use dd . Embora dd seja frequentemente anunciado como um comando de baixo nível para acessar dispositivos, na verdade não existe: toda a mágica acontece no arquivo do dispositivo (a parte /dev/… ), dd é apenas uma ferramenta comum com um alto potencial para uso indevido, resultando em perda de dados. Na maioria dos casos, existe uma maneira mais simples e segura de fazer o que você quer, pelo menos no Linux.
Por exemplo, para ler um determinado número de bytes no início de um arquivo, basta chamar head :
head -c 1000000m </dev/urandom >file
Fiz uma referência rápida em minha máquina e não observei nenhuma diferença de desempenho entre dd com um tamanho de bloco grande e head .
Se você precisar pular alguns bytes no início, canalize tail em head :
dd if=input of=output count=C bs=B seek=S
<input tail -c +$((S*B+1)) | head -c $((C*B)) >output
Se você quiser ver o progresso, chame lsof para ver o deslocamento do arquivo. Isso só funciona em um arquivo normal (o arquivo de saída no seu exemplo), não em um dispositivo de caractere.
lsof -a -p 1234 -d 1
cat /proc/1234/fdinfo/1
Você pode ligar para pv para obter um relatório de progresso (melhor que dd ), à custa de um item adicional no pipeline (em termos de desempenho, é quase imperceptível).