dd vs cat - dd è ancora rilevante in questi giorni?


122

Di recente ho capito che possiamo usare cattanto quanto dd, ed è in realtà più veloce didd

So che è ddstato utile nel trattare con nastri in cui le dimensioni del blocco contano davvero nella correttezza, non solo nelle prestazioni. In questi giorni, tuttavia, ci sono situazioni in cui ddqualcosa catpuò fare? (Qui considererei irrilevante una differenza di prestazione inferiore al 20%.)

Esempi concreti sarebbero belli!


1
Vedi questa domanda SO per un esempio concreto.
Camh,

Risposte:


156

In apparenza, ddè uno strumento di un sistema operativo IBM che ha conservato il suo aspetto estraneo (passaggio dei suoi parametri), che svolge alcune funzioni usate molto raramente (come conversioni da EBCDIC a ASCII o inversione di endianness ... non è un bisogno comune al giorno d'oggi).

Ho usato a pensare che ddera più veloce per la copia di grandi blocchi di dati sullo stesso disco (a causa di un uso più efficiente del buffer), ma questo non è vero , almeno su sistemi Linux di oggi.

Penso che alcune delle ddopzioni siano utili quando si ha a che fare con i nastri, in cui la lettura viene realmente eseguita in blocchi (i driver del nastro non nascondono i blocchi sul supporto di archiviazione come fanno i driver del disco). Ma non conosco i dettagli.

Una cosa ddche non può essere (facilmente) eseguita da qualsiasi altro strumento POSIX è prendere i primi N byte di un flusso. Molti sistemi possono farlo con head -c 42, ma head -c, sebbene comune, non è in POSIX (e non è disponibile oggi su OpenBSD ad esempio). ( tail -cè POSIX.) Inoltre, anche dove head -cesiste, potrebbe leggere troppi byte dall'origine (perché utilizza internamente lo stdio buffering), il che è un problema se stai leggendo da un file speciale in cui solo la lettura ha un effetto. (I coreutils GNU attuali leggono il conteggio esatto head -c, ma FreeBSD e NetBSD usano stdio.)

Più in generale, ddfornisce un'interfaccia all'API del file sottostante che è unica tra gli strumenti Unix: ddpuò solo sovrascrivere o troncare un file in qualsiasi momento o cercare in un file. (Questa è ddl'abilità unica ed è grande; stranamente ddè meglio conosciuto per le cose che altri strumenti possono fare.)

  • La maggior parte degli strumenti Unix sovrascrive il loro file di output, cioè cancella il suo contenuto e ricomincia da capo. Questo è ciò che accade anche quando si utilizza il >reindirizzamento nella shell.
  • È possibile aggiungere al contenuto di un file con il >>reindirizzamento nella shell o con tee -a.
  • Se si desidera abbreviare un file rimuovendo tutti i dati dopo un certo punto , questo è supportato dal kernel sottostante e dall'API C attraverso la truncatefunzione, ma non esposto da alcuno strumento da riga di comando trannedd :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • Se vuoi sovrascrivere i dati nel mezzo di un file, di nuovo, questo è possibile nell'API underyling aprendo il file per la scrittura senza troncare (e chiamando lseekper spostare nella posizione desiderata, se necessario), ma ddpuò solo aprire un file senza troncare o aggiungere o cercare dalla shell ( esempio più complesso ).

    # 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
    

Quindi ... Come strumento di sistema, ddè praticamente inutile. Come strumento di elaborazione di testo (o file binario), è piuttosto prezioso!


Accettato perché penso che spieghi l'essenza delle altre risposte ( trunced seekessendo utilizzabile da dd).
kizzx2,

2
Un altro uso speciale: ddpuò leggere dati binari da descrittori di file non ricercabili senza potenzialmente distruggere i dati non letti a causa del buffering stdio. Vedi qui per un esempio: etalabs.net/sh_tricks.html
R ..

2
@R ..: Sì. In GNU coreutils 6.10, head -c Nchiama reade non va mai oltre N. In NetBSD 5.1, head -cchiama getc. In FreeBSD 7.4, head -cchiama fread.
Gilles,

1
Coreutils ddespone anche O_DIRECT (ecc.) Alla shell scripting, che penso sia anche unica.
derobert il

1
Coreutils truncateconsente di troncare o estendere i file, eliminando così un altro uso di dd.
dcoles

22

Il ddcomando include MOLTE opzioni che cat non è in grado di accogliere. Forse nei tuoi casi d'uso cat è un sostituto praticabile, ma non è un sostituto dd.

Un esempio sarebbe usare ddper copiare parte di qualcosa ma non l'intera cosa. Forse vuoi estrarre alcuni dei bit dal centro di un'immagine iso o della tabella delle partizioni da un disco rigido basato su una posizione nota sul dispositivo. Con ddè possibile specificare le opzioni di avvio, arresto e quantità che consentono queste azioni.

Queste opzioni ddlo rendono indispensabile per la manipolazione dei dati a grana fine mentre cat* può operare solo su oggetti file interi, dispositivi o flussi.

* Come osservato da Gilles nei commenti, è possibile combinare catcon altri strumenti per isolare parti di qualcosa, ma catfunziona ancora sull'intero oggetto.


5
ddin realtà non ha nulla a che fare con i dispositivi di basso livello, ha bisogno di entrare /devcome gli altri. È possibile copiare un'intera partizione con cato parte di essa con tail +c $(($start+1)) | head -c $count.
Gilles,

16
Ovviamente. ;-) E quando inserisco un'immagine del disco da 1,6 TB cat | head | tailper recuperare gli ultimi MB, il disco che ruota verso l'alto risucchia la luna più vicino alla terra.
Caleb,

2
@Gilles Mi dispiace, ho voluto ammettere che il mio uso del termine "basso livello" non era una dizione molto buona, sebbene mi riferissi ai dati sui dispositivi, non sui dispositivi. Forse la "manipolazione dei dati ottimizzata" sarebbe meglio della "manipolazione dei dati di basso livello".
Caleb,

21

Nessuno ha ancora detto che è possibile utilizzare dd per creare file sparsi , anche se truncatepuò essere utilizzato anche per lo stesso scopo.

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

Questo è quasi istantaneo e crea un file di grandi dimensioni arbitrario che può essere utilizzato come file di loopback, ad esempio:

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

La cosa bella è che inizialmente utilizza solo un singolo blocco di spazio su disco, e successivamente cresce solo quando necessario (la formattazione ext4 di un file da 10 GB consuma 291 MB sul mio sistema). Utilizzare duper vedere quanto spazio su disco è effettivamente utilizzato: lssegnala solo la dimensione massima a cui il file può crescere.


4
ls -lsti mostra le dimensioni sparse.
jmtd,

2
Il tuo comando scrive un byte inutile nel file. dd of=sparse-file bs=1 count=0 seek=10Gsarebbe equivalente a truncate -s 10GB sparse-file. Abbastanza confusamente, truncatee ddhanno un'interpretazione esattamente opposta di GBvs. G...
frostschutz

5
@frostschutz: man dddice: MB =1000*1000, M =1024*1024e così via. E man truncatedice:, MB 1000*1000, M 1024*1024quindi non c'è differenza. Io uso sia dde truncatedalle coreutils GNU. Dovresti farlo anche tu! :-)
erik,

@erik: grazie per la correzione. Se non è stato modificato di recente, devo averlo confuso con qualcos'altro in qualche modo.
frostschutz,

10

Sostituire segmenti specifici di un disco rigido con qualcosa è un esempio comune. Ad esempio, potresti voler eliminare il tuo MBR usando questo comando:

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

Inoltre puoi creare file vuoti con esso (ad esempio per le immagini del disco loop):

dd if=/dev/zero of=10mb.file bs=1024k count=10

A parte questo secondo comando è il modo più veloce che io conosca di usare fino a 10 MB
Kevin M,

3
@Kevin: più veloce di head -c? Per favore condividi un benchmark !
Gilles,

9

ddè molto utile per eseguire il backup del settore di avvio di un disco rigido o di un altro dispositivo di archiviazione ( dd if=/dev/sda of=boot_sector.bin bs=512 count=1) e successivamente riscriverlo ( dd if=boot_sector.bin of=/dev/sda). È altrettanto utile per il backup delle intestazioni di volumi crittografati.

catpotrebbe essere contorto nel farlo, ma non mi fiderei della parte di riscrittura. È difficile catleggere / scrivere solo un certo numero di byte.


5

Di recente ho avuto la possibilità di clonare alcune partizioni multiple da 100s per GB per la prima volta nella mia storia di linux (cf cp -aro rsyncche mi hanno servito bene molte volte). Ovviamente mi sono rivolto a ddperché tutti sanno che è quello che usi ... ed è stato sconvolto dalla performance. Un po 'di ricerche su google mi hanno portato presto a ddrescue, che ho usato alcune volte e funziona perfettamente (molto più veloce di dd).


1
ddrescueè ottimo, soprattutto per ottenere dati da dischi difettosi.
reno il

5

Ecco alcuni trucchi dd che ho escogitato negli anni ..

Taglia e incolla su tty ostile o in modalità non interattiva bash

Se ti trovi in ​​una situazione in cui EOF / ^ D / ^ F non viene rilevato, puoi usare dd per trasferire file di testo su un host. Dal momento che smetterà di leggere automaticamente dopo un determinato numero di byte.

L'ho usato solo l'anno scorso durante un esercizio di sicurezza in cui siamo riusciti a ottenere shell non tty su un host remoto e dovevamo trasferire i file.

In effetti, ho anche fatto un paio di file binari codificandoli in base64 e usando uno script di decodifica base64 lento ma affidabile.

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

Un trucco super cool è che mentre dd è in esecuzione, se gli invii un segnale USR1, emetterà il suo stato corrente (byte letti, byte al secondo ..)

Filtro stato throughput universale

Ho scritto questo per fungere da puro filtro di avanzamento bash per qualsiasi programma che emette dati tramite stdout. (Nota: praticamente qualsiasi cosa emetterà dati tramite stdout - per i programmi che non lo fanno, puoi imbrogliare se non ti rubano usando / dev / stdout come nome file. Ma l'idea è fondamentalmente, ogni volta che ottieni X quantità di byte, segni di hash di stampa (come FTP della vecchia scuola quando era attiva la modalità hash)

(Nota) La cosa del file di progresso è scadente, questa era principalmente una prova del concetto. Se lo ripetessi, utilizzerei solo una variabile.

 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

file slice-and-dice usando filehandle di shell anonimi

Ecco un esempio estremamente pseudo-codice di come è possibile avere un file tar firmato che è possibile estrarre senza errori fornendo input tar tramite un filehandle anonimo - senza utilizzare alcun file tmp per archiviare i dati parziali del file.

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

Il tl; dr è: trovo che dd sia incredibilmente utile. E questi sono solo i tre esempi a cui riesco a pensare dalla cima della mia testa.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.