dd vs cat - ist dd heutzutage noch relevant?


122

Ich habe kürzlich festgestellt, dass wir catso viel verwenden können dd, und es ist tatsächlich schneller alsdd

Ich weiß, dass dddies beim Umgang mit Bändern nützlich war, bei denen die Blockgröße tatsächlich für die Korrektheit und nicht nur für die Leistung von Bedeutung war. Gibt es heutzutage Situationen, in denen ddetwas catnicht geht? (Hier würde ich einen Leistungsunterschied von weniger als 20% für irrelevant halten.)

Konkrete Beispiele wären schön!


1
Siehe diese SO-Frage für ein konkretes Beispiel.
Camh

Antworten:


156

In der Darstellung ddhandelt es sich um ein Tool eines IBM-Betriebssystems, dessen fremdes Erscheinungsbild (Übergabe von Parametern) beibehalten wurde und das einige sehr selten verwendete Funktionen ausführt (wie die Konvertierung von EBCDIC in ASCII oder die Umkehrung von Endianness… ist heutzutage nicht mehr erforderlich).

Ich pflegte zu denken , dass ddwar schneller zum Kopieren großer Datenblöcke auf derselben Platte (aufgrund einer effizienteren Nutzung der Pufferung), aber das ist nicht wahr , zumindest auf dem heutigen Linux - Systemen.

Ich denke, einige der ddOptionen sind nützlich, wenn es um Bänder geht, bei denen das Lesen wirklich in Blöcken erfolgt (Bandtreiber verbergen die Blöcke auf dem Speichermedium nicht so wie Plattentreiber). Aber ich kenne die Einzelheiten nicht.

Eine Sache dd, die (leicht) von keinem anderen POSIX-Tool erledigt werden kann, ist , die ersten N Bytes eines Streams zu nehmen. Viele Systeme können damit umgehen head -c 42, aber head -cobwohl es üblich ist, ist es nicht in POSIX (und ist heute nicht verfügbar unter zB OpenBSD). ( tail -cist POSIX.) Auch wenn head -cvorhanden, liest es möglicherweise zu viele Bytes aus der Quelle (da es intern die Stdio-Pufferung verwendet). Dies ist ein Problem, wenn Sie aus einer speziellen Datei lesen, bei der nur das Lesen Auswirkungen hat. (Aktuelle GNU-Coreutils lesen die genaue Anzahl mit head -c, FreeBSD und NetBSD verwenden jedoch stdio.)

Im Allgemeinen wird ddeine Schnittstelle zur zugrunde liegenden Datei-API bereitgestellt, die für Unix-Tools einzigartig ist: Sie ddkann eine Datei nur zu einem bestimmten Zeitpunkt überschreiben oder abschneiden oder in einer Datei suchen . (Dies ist eine einzigartige Fähigkeit, und es ist eine große; seltsamerweise ist sie am besten für Dinge bekannt, die andere Werkzeuge tun können.)dddd

  • Die meisten Unix-Tools überschreiben ihre Ausgabedatei, dh löschen ihren Inhalt und starten sie neu. Dies ist der Fall, wenn Sie die >Umleitung auch in der Shell verwenden.
  • Sie können den Inhalt einer Datei mit >>Umleitung in der Shell oder mit anhängen tee -a.
  • Wenn Sie eine Datei kürzen möchten, indem Sie nach einem bestimmten Zeitpunkt alle Daten entfernen , wird dies vom zugrunde liegenden Kernel und der C-API über die truncateFunktion unterstützt, jedoch von keinem Befehlszeilentool mit Ausnahme vondd :

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • Wenn Sie Daten in der Mitte einer Datei überschreiben möchten, ist dies in der Underyling-API ebenfalls möglich, indem Sie die Datei zum Schreiben öffnen , ohne sie abzuschneiden (und lseekgegebenenfalls an die gewünschte Position zu verschieben). Sie können jedoch nur ddeine Datei ohne öffnen Abschneiden oder Anhängen oder Suchen in der Shell ( komplexeres Beispiel ).

    # 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
    

Also ... Als Systemwerkzeug ddist es so ziemlich nutzlos. Als Textverarbeitungsprogramm (oder Binärdatei) ist es sehr wertvoll!


Akzeptiert, weil ich denke, es erklärt den Kern der anderen Antworten ( truncund seekverwendbar von dd).
kizzx2

2
Eine weitere spezielle Verwendung: ddKann Binärdaten aus nicht durchsuchbaren Dateideskriptoren lesen, ohne dass ungelesene Daten aufgrund der Stdio-Pufferung zerstört werden. Ein Beispiel finden Sie hier: etalabs.net/sh_tricks.html
R ..

2
@R ..: Ja. In GNU coreutils 6.10 head -c NAnrufe readund geht nie über N. in NetBSD 5.1, head -cfordert getc. In FreeBSD 7.4, head -cfordert fread.
Gilles

1
Coreutils ddstellt O_DIRECT (usw.) auch für Shell-Skripte zur Verfügung, was meiner Meinung nach ebenfalls einzigartig ist.
Derobert

1
Coreutils truncateermöglicht das Abschneiden oder Erweitern von Dateien, wodurch eine andere Verwendung von wegfällt dd.
dcoles

22

Der ddBefehl enthält VIELE Optionen, die cat nicht verarbeiten kann. Vielleicht ist cat in Ihren Anwendungsfällen ein brauchbarer Ersatz, aber kein Ersatz für dd.

Ein Beispiel wäre, ddeinen Teil von etwas zu kopieren, aber nicht das Ganze. Vielleicht möchten Sie einige der Bits aus der Mitte eines ISO-Images oder der Partitionstabelle von einer Festplatte basierend auf einem bekannten Speicherort auf dem Gerät entfernen. Mit können ddSie die Start-, Stopp- und Mengenoptionen angeben, die diese Aktionen ermöglichen.

Diese Optionen ddmachen es für feinkörnige Datenmanipulationen unverzichtbar, wohingegen cat* nur ganze Dateiobjekte, Geräte oder Streams verarbeiten kann.

* Wie Gilles in den Kommentaren angemerkt hat, ist es möglich cat, Teile von etwas mit anderen Werkzeugen zu isolieren, arbeitet aber catimmer noch mit dem gesamten Objekt.


5
ddHat eigentlich nichts mit Low-Level-Geräten zu tun, es braucht einen Einstieg /devwie bei den anderen. Sie können eine ganze Partition mit catoder einen Teil davon mit kopieren tail +c $(($start+1)) | head -c $count.
Gilles

16
Na sicher. ;-) Und wenn ich ein 1,6-TB-Image einspeise cat | head | tail, um die letzten MB abzurufen, wird der Mond durch das Hochdrehen der Festplatte näher an der Erde angesaugt.
Caleb

2
@Gilles Entschuldigung, ich wollte damit einverstanden sein, dass meine Verwendung des Begriffs "niedriger Pegel" keine sehr gute Wendung war, obwohl ich mich auf Daten auf Geräten bezog, nicht auf Geräte. Vielleicht wäre eine "fein abgestimmte Datenmanipulation" besser als eine "Manipulation von Daten auf niedriger Ebene".
Caleb

21

Bisher hat noch niemand erwähnt, dass Sie mit dd spärliche Dateien erstellen können , diese truncatekönnen jedoch auch für den gleichen Zweck verwendet werden.

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

Dies geschieht fast augenblicklich und erstellt eine beliebige große Datei, die beispielsweise als Loopback-Datei verwendet werden kann:

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

Das Schöne ist, dass es anfangs nur einen einzigen Block Speicherplatz belegt und danach nur noch nach Bedarf wächst (die ext4-Formatierung einer 10-GB-Datei belegt auf meinem System 291 MB). Verwenden Sie dudiese Option , um zu ermitteln, wie viel Speicherplatz tatsächlich verwendet lswird. Sie gibt nur die maximale Größe an, auf die die Datei anwachsen kann.


4
ls -lszeigt dir die spärliche Größe.
7.

2
Ihr Befehl schreibt ein unbrauchbares Byte in die Datei. dd of=sparse-file bs=1 count=0 seek=10Gwäre äquivalent zu truncate -s 10GB sparse-file. Verwirrenderweise truncateund ddgenau entgegengesetzte Interpretation von GBvs. G...
Frostschutz

5
@frostschutz: man ddsagt: MB =1000*1000, M =1024*1024und so weiter. Und man truncatesagt: Es MB 1000*1000, M 1024*1024gibt also keinen Unterschied. Ich benutze beide ddund truncateaus dem GNU Coreutils. Das solltest du auch! :-)
erik

@erik: Danke für die Korrektur. Wenn es nicht kürzlich geändert wurde, muss ich es irgendwie mit etwas anderem verwechselt haben.
Frostschutz

10

Ein häufiges Beispiel ist das Überschreiben bestimmter Segmente einer Festplatte mit etwas. Beispielsweise möchten Sie Ihren MBR möglicherweise mit folgendem Befehl löschen:

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

Sie können damit auch leere Dateien erstellen (z. B. für Loop-Disk-Images):

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

Abgesehen davon ist dieser zweite Befehl der schnellste Weg, den ich kenne, um 10 MB zu verbrauchen
Kevin M

3
@ Kevin: Schneller als head -c? Bitte teilen Sie einen Benchmark !
Gilles

9

ddist sehr nützlich, um den Bootsektor einer Festplatte oder eines anderen Speichergeräts zu sichern ( dd if=/dev/sda of=boot_sector.bin bs=512 count=1) und ihn später neu zu schreiben ( dd if=boot_sector.bin of=/dev/sda). Es ist ebenfalls nützlich, um die Header verschlüsselter Volumes zu sichern.

catVielleicht könnte ich das tun, aber ich würde es nicht dem Teil des Umschreibens anvertrauen. Es ist schwierig, catnur eine bestimmte Anzahl von Bytes zu lesen / schreiben.


5

Ich hatte kürzlich Grund, zum ersten Mal in meiner Linux-Geschichte einige Partitionen mit mehreren hundert GB zu klonen (vgl. cp -arOder rsyncdie mir schon oft gute Dienste geleistet haben). Natürlich habe ich mich gewandt dd, weil jeder weiß, dass du das verwendest ... und war entsetzt über die Aufführung. Ein bisschen googeln führte mich bald zu ddrescue, was ich jetzt schon ein paar Mal benutzt habe und hervorragend funktioniert (viel schneller als dd).


1
ddrescueist großartig, insbesondere, um Daten von fehlerhaften Festplatten abzurufen.
Ryenus

5

Hier sind einige DD-Tricks, die ich mir über die Jahre ausgedacht habe.

Ausschneiden und Einfügen bei unfreundlichem oder nicht interaktivem Bash

Wenn Sie sich in einer Situation befinden, in der EOF / ^ D / ^ F nicht erkannt wird, können Sie dd verwenden, um Textdateien auf einen Host zu übertragen. Da es nach einer festgelegten Anzahl von Bytes automatisch aufhört zu lesen.

Ich habe dies erst letztes Jahr während einer Sicherheitsübung verwendet, bei der es uns möglich war, Nicht-Tty-Shells auf einem Remote-Host abzurufen und Dateien zu übertragen.

Tatsächlich habe ich sogar ein paar Binärdateien erstellt, indem ich sie mit base64 codiert und ein langsames, aber zuverlässiges Base64-Decodierungsskript für reine Bash-Dateien verwendet habe.

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

Ein super cooler Trick ist, dass während dd läuft, wenn Sie ein USR1-Signal senden, es seinen aktuellen Status ausgibt (gelesene Bytes, Bytes pro Sekunde ..)

Universeller Durchsatzstatusfilter

Ich habe dies geschrieben, um als reiner Bash-Fortschrittsfilter für jedes Programm zu fungieren, das Daten über stdout ausgibt. (Hinweis: Fast alles gibt Daten über stdout aus. Bei Programmen, die dies nicht tun, können Sie schummeln, wenn sie Sie nicht mit / dev / stdout als Dateinamen belästigen. Grundsätzlich gilt jedoch, dass Sie jedes Mal X erhalten Anzahl der Bytes, Drucken von Hash-Markierungen (wie bei FTP der alten Schule, wenn der Hash-Modus aktiviert war)

(Anmerkung) Die Sache mit der Fortschrittsdatei ist lahm, dies war größtenteils ein Proof of Concept. Wenn ich es überarbeite, würde ich nur eine Variable verwenden.

 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

Slice-and-Dice-Dateien mit anonymen Shell-Dateihandles

Hier ist ein extrem pseudocodiertes Beispiel dafür, wie Sie eine signierte TAR-Datei haben können, die Sie ohne Fehler extrahieren können, indem Sie die TAR-Eingabe über ein anonymes Dateihandle bereitstellen - ohne TMP-Dateien zum Speichern von Teildateidaten zu verwenden.

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

Die Antwort lautet: Ich finde dd unglaublich nützlich. Und dies sind nur die drei Beispiele, die mir auf den ersten Blick einfallen.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.