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).