it-swarm.com.de

dd vs cat - ist dd heutzutage noch relevant?

Ich habe kürzlich festgestellt, dass wir cat genauso oft verwenden können wie dd, und es ist tatsächlich schneller als dd

Ich weiß, dass dd 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. In diesen Tagen gibt es jedoch Situationen, in denen dd etwas kann, was cat nicht kann? (Hier würde ich einen Leistungsunterschied von weniger als 20% für irrelevant halten.)

Konkrete Beispiele wären schön!

129
kizzx2

In der Darstellung ist dd ein Tool eines IBM-Betriebssystems, das sein fremdes Erscheinungsbild (seine Parameterübergabe) beibehalten hat und einige sehr selten verwendete Funktionen ausführt (z. B. EBCDIC an ASCII Konvertierungen oder Endianness-Umkehrung (heutzutage kein alltägliches Bedürfnis).

Ich dachte früher dass dd schneller war, um große Datenblöcke auf dieselbe Festplatte zu kopieren (aufgrund der effizienteren Verwendung der Pufferung), aber dies ist nicht wahr , zumindest auf heutigen Linux-Systemen.

Ich denke, einige der Optionen von dd sind nützlich, wenn es um Bänder geht, bei denen das Lesen wirklich in Blöcken ausgeführt wird (Bandtreiber verbergen die Blöcke auf dem Speichermedium nicht wie Festplattentreiber). Aber ich kenne die Einzelheiten nicht.

Eine Sache, die dd tun kann, die von keinem anderen POSIX-Tool (einfach) ausgeführt werden kann, ist die ersten N Bytes eines Streams zu nehmen. Viele Systeme können dies mit head -c 42 Tun, aber head -c Ist zwar üblich, aber nicht in POSIX (und heute unter OpenBSD nicht verfügbar). (tail -c Ist POSIX.) Selbst wenn head -c Vorhanden ist, werden möglicherweise zu viele Bytes aus der Quelle gelesen (da intern Stdio-Pufferung verwendet wird). Dies ist ein Problem, wenn Sie lesen aus einer speziellen Datei, in der nur das Lesen eine Wirkung hat. (Aktuelle GNU Coreutils lesen die genaue Anzahl mit head -c, Aber FreeBSD und NetBSD verwenden stdio.)

Im Allgemeinen bietet dd eine Schnittstelle zur zugrunde liegenden Datei-API, die unter Unix-Tools eindeutig ist: Nur dd kann eine Datei überschreiben oder abschneiden an einem beliebigen Punkt oder in einer Datei suchen . (Dies ist die einzigartige Fähigkeit von dd, und es ist eine große; seltsamerweise ist dd am besten für Dinge bekannt, die andere Tools tun können.)

  • Die meisten Unix-Tools überschreiben ihre Ausgabedatei, d. H. Löschen ihren Inhalt und starten sie von vorne. Dies passiert, wenn Sie die > - Umleitung auch in der Shell verwenden.
  • Sie können den Inhalt einer Datei mit der Umleitung >> In der Shell oder mit tee -a Anhängen.
  • Wenn Sie eine Datei kürzen möchten, indem Sie alle Daten nach einem bestimmten Punkt entfernen, wird dies vom zugrunde liegenden Kernel und der C-API über truncate unterstützt Funktion, aber von keinem Befehlszeilenprogramm verfügbar gemacht außer dd :

    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 wieder möglich, indem Öffnen die Datei zum Schreiben ohne Abschneiden (und Aufrufen von lseek) , um bei Bedarf an die gewünschte Position zu gelangen), aber nur dd kann eine Datei öffnen, ohne sie abzuschneiden oder anzuhängen, oder suchen aus 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 ist dd so ziemlich nutzlos. Als Textverarbeitungswerkzeug (oder Binärdatei) ist es sehr wertvoll!

Der Befehl dd enthält VIELE Optionen, die cat nicht berücksichtigen kann. Vielleicht ist Katze in Ihren Anwendungsfällen ein praktikabler Ersatz, aber kein DD-Ersatz.

Ein Beispiel wäre die Verwendung von dd, um einen 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 herausreißen, basierend auf einem bekannten Speicherort auf dem Gerät. Mit dd können Sie die Start-, Stopp- und Mengenoptionen angeben, die diese Aktionen ermöglichen.

Diese Optionen von dd machen es für eine feinkörnige Datenmanipulation unverzichtbar, während cat * nur für ganze Dateiobjekte, Geräte oder Streams ausgeführt werden kann.

* Wie Gilles in den Kommentaren bemerkt hat, ist es möglich, cat mit anderen Werkzeugen zu kombinieren, um Teile von etwas zu isolieren, aber cat funktioniert immer noch für das gesamte Objekt.

22
Caleb

Bisher hat noch niemand erwähnt, dass Sie mit dd spärliche Dateien erstellen können, obwohl truncate auch für denselben Zweck verwendet werden kann.

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

Dies ist 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 zunächst nur ein einziger Block Speicherplatz verwendet wird und danach nur noch nach Bedarf wächst (die ext4-Formatierung einer 10-GB-Datei verbraucht auf meinem System 291 MB). Verwenden Sie du, um zu sehen, wie viel Speicherplatz tatsächlich verwendet wird. ls gibt nur die maximale Größe an, auf die die Datei wachsen darf.

21

Ein häufiges Beispiel ist das Überschreiben bestimmter Segmente einer Festplatte mit etwas. Beispielsweise möchten Sie Ihren MBR möglicherweise mit diesem 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
10
XQYZ

dd ist sehr nützlich zum Sichern des Bootsektors einer Festplatte oder eines anderen Speichergeräts (dd if=/dev/sda of=boot_sector.bin bs=512 count=1) und später umschreiben (dd if=boot_sector.bin of=/dev/sda). Es ist ähnlich nützlich, um die Header verschlüsselter Volumes zu sichern.

cat könnte dazu verdreht werden, aber ich würde es beim Umschreiben nicht vertrauen. Es ist schwierig, cat dazu zu bringen, nur eine bestimmte Anzahl von Bytes zu lesen/schreiben.

9
LawrenceC

Ich hatte kürzlich Grund, zum ersten Mal in meiner Linux-Geschichte einige Partitionen mit mehreren 100 GB zu klonen (vgl. cp -ar oder rsync, die mir schon oft gute Dienste geleistet haben). Natürlich habe ich mich an dd gewandt, weil jeder weiß, dass Sie das verwenden ... und war entsetzt über die Leistung. Ein bisschen googeln führte mich bald zu ddrescue , das ich jetzt ein paar Mal verwendet habe und hervorragend funktioniert (viel schneller als dd).

5
timday

Hier sind einige dd Tricks, die ich mir im Laufe der Jahre ausgedacht habe.

Ausschneiden und Einfügen bei unfreundlichem tty oder nicht interaktivem Modus bash

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

Ich habe dies erst letztes Jahr während einer Sicherheitsübung verwendet, bei der wir nicht-tty-Shells auf einem Remote-Host abrufen konnten und Dateien übertragen mussten.

Tatsächlich habe ich sogar ein paar Binärdateien erstellt, indem ich sie mit base64 codiert und ein langsames, aber zuverlässiges reines Base64-Decodierungsskript verwendet habe.

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

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

niverseller Durchsatzzustandsfilter

Ich habe dies geschrieben, um als reiner Bash-Fortschrittsfilter für jedes Programm zu fungieren, das Daten über stdout ausgibt. (Hinweis: So ziemlich alles gibt Daten über stdout aus - für Programme, die dies nicht tun, können Sie betrügen, wenn sie Sie nicht mit/dev/stdout als Dateinamen belasten. Die Idee ist jedoch im Grunde, jedes Mal, wenn Sie X erhalten Anzahl der Bytes, drucken Sie Hash-Markierungen (wie FTP der alten Schule, wenn Sie den Hash-Modus aktiviert hatten)

(Hinweis) Die Sache mit der Fortschrittsdatei ist lahm, dies war größtenteils ein Proof of Concept. Wenn ich es überarbeiten würde, 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 extremes Pseudocode-Beispiel dafür, wie Sie eine signierte TAR-Datei haben können, die Sie fehlerfrei extrahieren können, indem Sie TAR-Eingaben ü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})

Das Wichtigste ist: Ich finde dd unglaublich nützlich. Und dies sind nur die drei Beispiele, die mir auf den ersten Blick einfallen.

5

Sie können einige Ausgabeinhalte umleiten. Dies ist besonders nützlich, wenn Sie mit Sudo schreiben müssen:

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

Neben Sudo entspricht es:

echo some_content > output.txt

oder dazu:

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