
Eu crio um arquivo de 1 TB com dados aleatórios com extensão dd if=/dev/urandom of=file bs=1M count=1000000
. Agora verifico kill -SIGUSR1 <PID>
o progresso e obtenho o seguinte:
691581+0 Datensätze ein
691580+0 Datensätze aus
725174190080 Bytes (725 GB) kopiert, 86256,9 s, 8,4 MB/s
800950+1 Datensätze ein
800950+0 Datensätze aus
839856947200 Bytes (840 GB) kopiert, 99429,5 s, 8,4 MB/s
dd: warning: partial read (809620 bytes); suggest iflag=fullblock
803432+1 Datensätze ein
803431+1 Datensätze aus
842459273876 Bytes (842 GB) kopiert, 99791,3 s, 8,4 MB/s
Não consigo interpretar o aviso. O que isso diz? Meu arquivo é realmente aleatório após o aviso ou há algum problema? O que significa +0 ou +1 em 800950+1 Datensätze ein
e 800950+0 Datensätze aus
? Após o aviso é +1. É uma contagem de erros?
Responder1
Resumo: dd
é uma ferramenta complicada e difícil de usar corretamente. Não o use, apesar dos inúmeros tutoriais que dizem isso. dd
tem uma vibração de “credibilidade de rua unix” associada a ele - mas se você realmente entende o que está fazendo, saberá que não deveria tocá-lo com uma vara de 3 metros.
dd
faz uma única chamada para a read
chamada do sistema por bloco (definido pelo valor de bs
). Não há garantia de que a read
chamada do sistema 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. VerQuando o dd é adequado para copiar dados? (ou, quando read() e write() são parciais)Para maiores informações. Se a read
chamada do sistema retornar menos de um bloco completo, dd
transfere um bloco parcial. Ele ainda copia o número especificado de blocos, portanto a quantidade total de bytes transferidos é menor que a solicitada.
O aviso sobre uma “leitura parcial” diz exatamente isso: uma das leituras foi parcial, então dd
transferiu um bloco incompleto. Nas contagens de blocos, +1
significa que um bloco foi lido parcialmente; como a contagem de saída é +0
, todos os blocos foram escritos como lidos.
Isso não afeta a aleatoriedade dos dados: todos os bytes gravados dd
são bytes lidos /dev/urandom
. Mas você obteve menos bytes do que o esperado.
O Linux /dev/urandom
acomoda grandes solicitações arbitrárias (fonte:extract_entropy_user
in drivers/char/random.c
), então 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 read
chamada do sistema retornará antes de preencher seu buffer de saída. Este é um comportamento normal e os aplicativos devem chamar read
em loop; dd
não faz isso, por razões históricas ( dd
as origens de são obscuras, mas parece ter começado como uma ferramenta de acesso a fitas, que possuem requisitos peculiares, e nunca foi adaptada para ser uma ferramenta de uso geral). Ao verificar o andamento, isso envia ao dd
processo um sinal que interrompe a leitura. Você pode escolher entre saber quantos bytes dd
serão copiados no total (certifique-se de não interrompê-lo - sem verificação de progresso, sem suspensão) ou saber quantos bytes dd
foram copiados até agora; nesse caso, você não pode saber quantos mais bytes que ele copiará.
A versão dedd
em GNU coreutils(como encontrado no Linux não embarcado e no Cygwin) possui um sinalizador fullblock
que informa dd
para chamar read
um loop (e o mesmo para write
) e, portanto, sempre transferir blocos completos. A mensagem de erro sugere que você o use; você deve sempre usá-lo (tanto nos sinalizadores de entrada quanto de saída), exceto em circunstâncias muito especiais (principalmente ao acessar fitas) — dd
isto é, se você usar: geralmente há soluções melhores (veja abaixo).
dd if=/dev/urandom iflag=fullblock of=file bs=1M count=1000000
Outra maneira possível de ter certeza do que dd
acontecerá é passar um tamanho de bloco 1. Então você pode saber quantos bytes foram copiados da contagem de blocos, embora eu não tenha certeza do que acontecerá se a read
for 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, é muito lento.
O conselho geral sobre o uso dd
énão usedd
. Embora dd
seja frequentemente anunciado como um comando de baixo nível para acessar dispositivos, na verdade não é tal coisa: toda a mágica acontece na parte do arquivo do dispositivo (a /dev/…
parte ), dd
é apenas uma ferramenta comum com alto potencial de uso indevido, resultando em perda de dados . Na maioria dos casos, existe uma maneira mais simples e segura de fazer o que você deseja, 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 um benchmark rápido em minha máquina e não observei nenhuma diferença de desempenho entre dd
blocos grandes e head
.
Se você precisar pular alguns bytes no início, canalize tail
para 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, ligue lsof
para ver o deslocamento do arquivo. Isso funciona apenas 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 ligarpv
para obter um relatório de progresso (melhor que dd
o do), às custas de um item adicional no pipeline (em termos de desempenho, é quase imperceptível).
Responder2
O aviso ocorre quando dd
não foi possível obter dados suficientes para preencher um bloco em uma única leitura. Isso acontece com fontes de dados erráticas ou lentas, ou fontes que gravam dados em unidades menores que o tamanho de bloco solicitado.
Não há problema com a integridade dos dados, mas o problema é que dd
uma leitura parcial ainda conta como um bloco de leitura.
Se você não estiver usando a count
opção, o aviso pouco importa, é apenas uma consideração de desempenho. Mas com count
você não obterá a quantidade de dados solicitada. Devido a leituras parciais, of
será menor que count*bs
no final.
Então, quando você usa count
, tecnicamente você deve sempre usar iflag=fullblock
também.
Deve +x
ser o número de blocos parciais.
Responder3
< /dev/urandom \
dd ibs=4k obs=64k |
dd bs=64k count=16000000 >file
^ Isso simplesmente funcionará. A desinformação aqui apresentada é manifestamente falsa. dd
Os buffers de sãoexplícitoe assim, para armazenar em buffer a entrada paracontarocorrências que você precisa armazenar explicitamente em buffer. Isso é tudo. Não compre o fud.