Eu crio um arquivo de 1 TB com dados aleatórios com dd if=/dev/urandom of=file bs=1M count=1000000
. Agora eu 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 diz isso? Meu arquivo é realmente aleatório após o aviso ou há algum problema? O que significa +0 ou +1 in 800950+1 Datensätze ein
e 800950+0 Datensätze aus
significa? Após o aviso, é +1. É uma contagem de erros?
LC_ALL=C
na frente do comando, comoLC_ALL=C dd if=...
Respostas:
Resumo:
dd
é uma ferramenta irritante que é difícil de usar corretamente. Não o use, apesar dos inúmeros tutoriais que lhe dizem isso.dd
tem uma vibração de "unix street cred", mas se você realmente entende o que está fazendo, saberá que não deve tocá-lo com uma vara de três metros.dd
faz uma única chamada para a chamada doread
sistema por bloco (definida pelo valor debs
). Não há garantia de que aread
chamada do sistema retorne tantos dados quanto o tamanho do buffer especificado. Isso costuma funcionar para arquivos regulares e dispositivos de bloco, mas não para pipes e alguns dispositivos de caracteres. Consulte Quando o dd é adequado para copiar dados? (ou, quando são lidos () e gravados () parciais) para obter mais informações. Se aread
chamada do sistema retornar menos de um bloco completo,dd
transferirá um bloco 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 isso: uma das leituras foi parcial, portanto
dd
transferiu um bloco incompleto. Na contagem de blocos,+1
significa que um bloco foi lido parcialmente; como a contagem de saída é+0
, todos os blocos foram gravados como lidos.Isso não afeta a aleatoriedade dos dados: todos os bytes
dd
gravados são bytes dos quais eles são lidos/dev/urandom
. Mas você tem menos bytes do que o esperado.O Linux
/dev/urandom
acomoda solicitações grandes e arbitrárias (fonte:extract_entropy_user
indrivers/char/random.c
), portantodd
normalmente é seguro ao ler a partir dele. No entanto, a leitura de grandes quantidades de dados leva tempo. Se o processo receber um sinal, aread
chamada do sistema retornará antes de preencher seu buffer de saída. Esse é um comportamento normal, e os aplicativos devem chamarread
em um loop;dd
não faz isso, por razões históricas (dd
as origens são obscuras, mas parece ter começado como uma ferramenta para acessar fitas, que têm requisitos peculiares e nunca foi adaptada para ser uma ferramenta de uso geral). Quando você verifica o progresso, isso envia aodd
processo um sinal que interrompe a leitura. Você pode escolher entre saber quantos bytesdd
será copiado no total (lembre-se de não interrompê-lo - sem verificação de progresso, sem suspensão) ou sabendo quantos bytesdd
foram copiados até agora; nesse caso, você não pode saber quantos bytes serão copiados.A versão do
dd
GNU coreutils (como encontrada no Linux não incorporado e no Cygwin) possui uma flagfullblock
que dizdd
para chamarread
um loop (e o mesmo parawrite
) e, portanto, sempre transfere blocos completos. A mensagem de erro sugere que você o use; você deve sempre usá-lo (nos sinalizadores de entrada e de saída), exceto em circunstâncias muito especiais (principalmente ao acessar fitas) - se você usardd
, ou seja: geralmente existem soluções melhores (veja abaixo).Outra maneira possível de ter certeza do que
dd
fará é passar o tamanho de um bloco de 1. Então, você pode dizer quantos bytes foram copiados da contagem de blocos, embora não tenha certeza do que acontecerá se umread
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, isso é muito lento.O conselho geral sobre o uso
dd
é não usardd
. Emboradd
seja frequentemente anunciado como um comando de baixo nível para acessar dispositivos, na verdade não existe: toda a mágica acontece na parte do arquivo do dispositivo/dev/…
,dd
é apenas uma ferramenta comum com um 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 certo número de bytes no início de um arquivo, basta chamar
head
:Fiz uma referência rápida na minha máquina e não observei nenhuma diferença de desempenho entre
dd
um tamanho de bloco grande ehead
.Se você precisar pular alguns bytes no início, entre
tail
emhead
:Se você quiser ver o progresso, ligue
lsof
para ver o deslocamento do arquivo. Isso funciona apenas em um arquivo regular (o arquivo de saída no seu exemplo), não em um dispositivo de caractere.Você pode ligar
pv
para obter um relatório de progresso (melhor quedd
o), às custas de um item adicional no pipeline (em termos de desempenho, é quase imperceptível).fonte
dd
comando que eu não sabia que precisava conhecer. Obrigado.dd
pode ser usado com segurança, graças à suafullblock
opção. Mas se você tem coreutils GNU, não precisa dedd
muito. “Derivativos” comodcfldd
eles não sãodd
, eles não sofrem com seus defeitos de design, portanto minha resposta não se aplica a eles. Uma vasta e vasta maioria das pessoas que usamdd
não levou tempo suficiente para entendê-lo (no máximo, gastou um tempo para pensar que o entendeu) e a maneira como elas o usam leva à perda de dados.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 do bloco solicitado.Não há problema com a integridade dos dados, mas o problema é que
dd
conta uma leitura parcial ainda como um bloco de leitura.Se você não estiver usando a
count
opção, o aviso dificilmente importa, é apenas uma consideração de desempenho. Mas comcount
, você não receberá a quantidade de dados solicitada. Devido a leituras parciais,of
será menor quecount*bs
no final.Então, quando você usa
count
, tecnicamente você deve sempre usariflag=fullblock
também.O
+x
deve ser o número de blocos parciais.fonte
^ Isso simplesmente funcionará. A desinformação de outra maneira aqui apresentada é manifestamente falsa.
dd
's buffers são explícita e por isso, para o buffer de entrada para contar as ocorrências que você precisa para o buffer de forma explícita. Isso é tudo. Não compre o fud.fonte