it-swarm.it

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

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

So che dd è stato utile per gestire i nastri in cui la dimensione del blocco contava effettivamente nella correttezza, non solo nelle prestazioni. In questi giorni, tuttavia, ci sono situazioni in cui dd può fare qualcosa cat non può? (Qui considererei irrilevante una differenza di prestazione inferiore al 20%.)

Esempi concreti sarebbero belli!

129
kizzx2

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

I pensavo che dd fosse più veloce per copiare grandi blocchi di dati sullo stesso disco (a causa di un uso più efficiente del buffering), ma questo non è vero , almeno sui sistemi Linux di oggi.

Penso che alcune delle opzioni di dd siano utili quando si ha a che fare con 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 che dd può fare e che non può (facilmente) essere eseguita da qualsiasi altro strumento POSIX è prendere i primi N byte di un streaming. 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 -c Esiste, potrebbe leggere troppi byte dall'origine (perché utilizza il buffering stdio internamente), il che è un problema se stai leggendo da un file speciale in cui solo la lettura ha un effetto. (Gli attuali coreutils GNU leggono il conteggio esatto con head -c, Ma FreeBSD e NetBSD usano stdio.)

Più in generale, dd fornisce un'interfaccia all'API del file sottostante unica tra gli strumenti Unix: solo dd può sovrascrivere o troncare un file in qualsiasi punto o cerca in un file. (Questa è l'abilità unica di dd, ed è grande, stranamente dd è meglio conosciuta per le cose che altri strumenti possono fare.)

  • La maggior parte degli strumenti Unix sovrascrive il loro file di output, ovvero cancella il suo contenuto e ricomincia da capo. Questo è ciò che accade quando si utilizza il reindirizzamento > Anche in Shell.
  • È possibile aggiungere al contenuto di un file con il reindirizzamento >> In 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 truncate funzione, ma non esposta da nessuno strumento da riga di comando tranne dd :

    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, ancora una volta, questo è possibile nell'API underyling apertura il file per scrivere senza troncare (e chiamare lseek per spostarsi nella posizione desiderata, se necessario), ma solo dd può aprire un file senza troncare o aggiungere, oppure 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!

Il comando dd 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 potrebbe essere l'uso di dd per copiare parte di qualcosa ma non l'intero. 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 puoi specificare le opzioni di avvio, arresto e quantità che consentono queste azioni.

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

* Come notato da Gilles nei commenti, è possibile combinare cat con altri strumenti per isolare parti di qualcosa, ma cat opera ancora sull'intero oggetto.

22
Caleb

Nessuno ha ancora detto che puoi usare dd per creare file sparsi , sebbene truncate possa essere usato 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). Usa du per vedere quanto spazio su disco è effettivamente utilizzato - ls indica solo la dimensione massima che il file può raggiungere.

21

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
10
XQYZ

dd è molto utile per 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 riscrivendolo (dd if=boot_sector.bin of=/dev/sda). È altrettanto utile per il backup delle intestazioni di volumi crittografati.

cat potrebbe essere contorto nel farlo, ma non mi fiderei della parte di riscrittura. È difficile ottenere cat per leggere/scrivere solo un certo numero di byte.

9
LawrenceC

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

5
timday

Ecco alcuni trucchi dd che ho escogitato negli anni ..

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

Se ti trovi in ​​una situazione in cui EOF/^ D/^ F non viene rilevato, puoi utilizzare 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 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.

5
synthesizerpatel

Puoi reindirizzare alcuni contenuti di output. È particolarmente utile, se devi scrivere con Sudo:

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

Oltre a Sudo è equivalente a:

echo some_content > output.txt

o a questo:

echo some_content | Sudo tee output.txt > /dev/null
5
Alexey