dd vs cat - dd ainda é relevante nos dias de hoje?

111

Recentemente, percebi que podemos usar cat tanto quanto dd , e é realmente mais rápido que dd

Eu sei que dd foi útil para lidar com fitas onde o tamanho do bloco realmente importava em correção, não apenas desempenho. Atualmente, existem situações em que dd pode fazer algo cat não pode? (Aqui eu consideraria uma diferença de desempenho inferior a 20% irrelevante.)

Exemplos concretos seriam legais!

    
por kizzx2 03.05.2011 / 16:18

8 respostas

152

Na aparência, dd é uma ferramenta de um sistema operacional da IBM que retém sua aparência estrangeira (sua passagem de parâmetro), que executa algumas funções muito raramente usadas (como conversões de EBCDIC para ASCII ou reversão de endianness ... não uma necessidade comum hoje em dia).

Eu achavam que dd era mais rápido para copiar grandes blocos de dados no mesmo disco (devido ao uso mais eficiente do buffer), mas isso não é verdade , pelo menos nos sistemas Linux de hoje.

Acho que algumas das opções de dd são úteis ao lidar com fitas, onde a leitura é realmente realizada em blocos (drivers de fita não escondem os blocos no meio de armazenamento como os drivers de disco fazem). Mas eu não sei os detalhes.

Uma coisa que o dd pode fazer que não pode (facilmente) ser feito por qualquer outra ferramenta POSIX é tomando os primeiros N bytes de um fluxo. Muitos sistemas podem fazê-lo com head -c 42 , mas head -c , embora seja comum, não está em POSIX (e não está disponível hoje, por exemplo, no OpenBSD). ( tail -c é POSIX.) Além disso, mesmo onde head -c existe, ele pode ler muitos bytes da origem (porque ele usa stdio buffering internamente), o que é um problema se você estiver lendo de um arquivo especial onde apenas a leitura tem um efeito. (Coreutils GNU atuais lêem a contagem exata com head -c , mas o FreeBSD e o NetBSD usam o stdio.)

Mais geralmente, dd fornece uma interface à API de arquivo subjacente que é única entre as ferramentas do Unix: somente dd pode substituir ou truncar um arquivo em qualquer ponto ou procura em um arquivo. (Esta é a habilidade única de dd , e é uma grande habilidade; por incrível que pareça, dd é mais conhecido por coisas que outras ferramentas podem fazer.)

  • A maioria das ferramentas Unix sobrescrevem o arquivo de saída, ou seja, apagam seu conteúdo e o iniciam do zero. É o que acontece quando você usa o redirecionamento > no shell também.
  • Você pode acrescentar ao conteúdo de um arquivo com >> de redirecionamento no shell ou com tee -a .
  • Se você quiser encurtar um arquivo removendo todos os dados após um certo ponto , isso é suportado pelo kernel subjacente e pela API C através do truncate funcionam, mas não são expostos por nenhuma ferramenta de linha de comando exceto dd :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • Se você quiser substituir os dados no meio de um arquivo, novamente, isso é possível na API do underyling por abrindo o arquivo para escrever sem truncar (e chamando lseek para mover para a posição desejada, se necessário), mas somente dd pode abrir um arquivo sem truncar ou acrescentar, ou procura a partir do shell ( exemplo mais complexo ).

    # zero out the second kB block in the file (i.e. bytes 1024 to 2047)
    dd if=/dev/zero of=/path/to/file bs=1024 seek=1 count=1 conv=notrunc
    

Então… Como uma ferramenta do sistema, dd é praticamente inútil. Como uma ferramenta de processamento de texto (ou arquivo binário), é muito valiosa!

    
por 03.05.2011 / 17:12
21

O comando dd inclui muitas opções que o gato não é capaz de acomodar. Talvez em seus casos de uso o gato seja um substituto viável, mas não é um substituto do dd.

Um exemplo seria usar dd para copiar parte de algo, mas não a coisa toda. Talvez você queira extrair alguns dos bits do meio de uma imagem iso ou da tabela de partição de um disco rígido com base em um local conhecido no dispositivo. Com dd , você pode especificar as opções de início, parada e quantidade que permitem essas ações.

Essas opções de dd tornam-no indispensável para a manipulação de dados refinados, enquanto o cat * só pode operar em objetos, dispositivos ou fluxos de arquivos inteiros.

* Como observado por Gilles nos comentários, é possível combinar cat com outras ferramentas para isolar partes de algo, mas cat ainda opera em todo o objeto.

    
por 03.05.2011 / 16:31
20

Ninguém mencionou ainda que você pode usar o dd para criar arquivos esparsos , embora truncate também possa ser usado para o mesmo fim.

dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB

Isso é quase instantâneo e cria um arquivo grande e arbitrário que pode ser usado como um arquivo de loopback por exemplo:

loop='losetup --show -f sparse-file'
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop

O bom é que inicialmente usa apenas um único bloco de espaço em disco e, a partir daí, cresce apenas conforme necessário (a formatação ext4 de um arquivo de 10 GB consome 291 MB no meu sistema). Use du para ver quanto espaço em disco é realmente usado - ls relata apenas o tamanho máximo para o qual o arquivo pode crescer.

    
por 04.05.2011 / 10:26
10

Substituir segmentos específicos de um disco rígido por algo é um exemplo comum. Por exemplo, você pode querer excluir seu MBR usando este comando:

dd if=/dev/zero of=/dev/sda bs=446 count=1

Além disso, você pode criar arquivos vazios com ele (digamos, para imagens de disco em loop):

dd if=/dev/zero of=10mb.file bs=1024k count=10
    
por 03.05.2011 / 16:25
9

dd é muito útil para fazer backup do setor de inicialização de um disco rígido ou de outro dispositivo de armazenamento ( dd if=/dev/sda of=boot_sector.bin bs=512 count=1 ) e depois reescrevê-lo ( dd if=boot_sector.bin of=/dev/sda ). É igualmente útil para fazer o backup dos cabeçalhos de volumes criptografados.

cat pode ser transformado em algo assim, mas eu não confiaria na parte de reescrita. É difícil obter cat somente para ler / escrever um certo número de bytes.

    
por 03.05.2011 / 20:23
5

Recentemente, tive a causa de clonar algumas partições de vários 100s-GB pela primeira vez em meu histórico de linuxing (c.f cp -ar ou rsync que me serviram bem várias vezes). Claro que eu virei para dd porque todos sabem que é o que você usa ... e ficou chocado com o desempenho. Um pouco de googling logo me levou a ddrescue , que usei algumas vezes agora e funciona muito bem (muito mais rápido que o dd).

    
por 03.05.2011 / 20:47
5

Aqui estão alguns truques do dd que eu criei ao longo dos anos.

Recortar e colar no modo hostil tty ou não interativo

Se você estiver em uma situação em que EOF / ^ D / ^ F não for detectado, poderá usar o dd para transferir arquivos de texto para um host. Desde que ele irá parar de ler depois de uma quantidade especificada de bytes automaticamente.

Eu usei isso recentemente, no ano passado, durante um exercício de segurança em que conseguimos obter shells não-tty em um host remoto e precisávamos transferir arquivos.

Na verdade, eu até fiz alguns arquivos binários por base64 codificando-os e usando um script de decodificação base64 de base pura e confiável.

dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>

Um truque super legal é que enquanto o dd está rodando, se você enviar um sinal USR1, ele emitirá seu status atual (bytes lidos, bytes por segundo ..)

Filtro de estado de throughput universal

Eu escrevi isso para agir como um filtro puro de progresso para qualquer programa que emite dados através do stdout. (Nota: praticamente qualquer coisa irá emitir dados através de stdout - para programas que não, você pode trapacear se eles não aparecerem em você usando / dev / stdout como um nome de arquivo. Mas a idéia é basicamente, toda vez que você obtém X quantidade de bytes, imprimir marcas de hash (como o FTP da velha escola quando você tinha o modo de hash)

(nota) A coisa do arquivo do progresso é coxa, isto era na maior parte uma prova do conceito. Se eu refizê-lo, usaria apenas uma variável.

 dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
                | grep --line-buffered -E '[[:digit:]]* bytes' \
                | awk '{ print $1 }' >> ${PROGRESS} &

 while [[ $(pidof dd) -gt 1 ]]; do

        # PROTIP: You can sleep partial seconds
        sleep .5

        # Force dd to update us on it's progress (which gets
        # redirected to $PROGRESS file.    
        pkill -USR1 dd
        local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
        local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))

        if [ $XFER_BLKS -gt 0 ]; then
                printf "#%0.s" $(seq 0 $XFER_BLKS)
                BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
        fi
done

arquivos de slice-and-dice usando filehandles de shell anônimos

Aqui está um exemplo extremamente pseudocódigo de como você pode ter um arquivo tar assinado que pode ser extraído sem erros fornecendo entrada tar por meio de um filehandle anônimo - sem usar nenhum arquivo tmp para armazenar dados parciais de arquivos.

generate_hash() {
    echo "yay!"
}

# Create a tar file, generate a hash, append it to the end
tar -cf log.tar /var/log/* 2>/dev/null
TARFILE_SIZE=$(stat -f "%z" log.tar)
SIGNATURE=$(generate_hash log.tar)
echo $SIGNATURE >>log.tar

# Then, later, extract without getting an error..

tar xvf <(dd if=$OLDPWD/log.tar bs=1 count=${TARFILE_SIZE})

O tl; dr é: acho que o dd é incrivelmente útil. E estes são apenas os três exemplos que posso pensar em cima da minha cabeça.

    
por 17.02.2014 / 12:51
4

Você pode redirecionar algum conteúdo de saída. É particularmente útil se você precisar escrever com sudo :

echo some_content | sudo dd status=none of=output.txt

Além de sudo , é equivalente a:

echo some_content > output.txt

ou para isso:

echo some_content | sudo tee output.txt > /dev/null
    
por 13.03.2018 / 13:20

Tags