dd vs cat — ddは今でも関連性がありますか?


122

私は最近、私たちが使用することができます実現cat限りdd、それはだ、実際よりも速くdd

これは、ddパフォーマンスだけでなく、ブロックサイズが正確に重要であるテープを扱うのに役立つことを知っています。しかし、最近では、ddできないことcatができる状況はありますか?(ここでは、パフォーマンスの差は20%未満であると見なします。)

具体的な例がいいでしょう!


1
具体的な例については、このSOの質問を参照してください。
カム

回答:


156

外観ddは、外部の外観(パラメーターの受け渡し)を保持するIBMオペレーティングシステムのツールであり、非常にまれにしか使用されない機能(EBCDICからASCIIへの変換やエンディアンの反転など、今日では一般的な必要性はありません)を実行します。

私が考えるために使用されることがdd速く(起因するバッファリングをより効率的に使用する)同じディスク上のデータの大きなブロックをコピーするためだったが、これは真実ではない、少なくとも今日のLinuxシステムでは、。

いくつかddのオプションは、読み取りが実際にブロックで実行されるテープを扱うときに便利だと思います(テープドライバーは、ディスクドライバーのようにストレージメディア上のブロックを隠しません)。しかし、私はその詳細を知りません。

dd他のPOSIXツールでは(簡単に)できないことの1つは、ストリームの最初のNバイト取得することです。多くのシステムでを使用できますhead -c 42head -c、は一般的ですが、POSIXには含まれていません(OpenBSDなどでは今日利用できません)。(tail -cPOSIXです。)また、head -c存在する場合でも、ソースから多くのバイトを読み取る可能性があります(内部でstdioバッファリングを使用するため)。これは、読み取りだけが有効な特殊ファイルから読み取る場合に問題になります。(現在のGNU coreutilsはで正確なカウントを読み取りhead -cますが、FreeBSDとNetBSDはstdioを使用します。)

より一般的には、ddUnixツールの中で一意である基本的なファイルAPIへのインターフェイスを提供します:のみdd可能上書きまたは切り捨てファイルを任意の時点で、または求めてファイルに。(これはddのユニークな能力であり、大きな能力です。奇妙なddことに、他のツールでできることで十分に知られています。)

  • ほとんどのUnixツールは、出力ファイルを上書きします。つまり、その内容を消去し、最初からやり直します。これは>、シェルでリダイレクトを使用する場合にも発生します。
  • >>シェルでリダイレクトするか、でファイルのコンテンツに追加できますtee -a
  • 特定のポイントの後にすべてのデータを削除してファイルを短くしたい場合、これはtruncate関数を介して基礎となるカーネルとC APIでサポートされますが、以下を除くddコマンドラインツールでは公開されません:

    dd if=/dev/null of=/file/to/truncate seek=1 bs=123456  # truncate file to 123456 bytes
    
  • あなたはファイルの途中でデータを上書きする場合は、再び、これはでunderyling APIで可能です開い切り捨て(と呼ばずに書き込み用のファイルをlseek必要に応じて任意の位置に移動する)が、唯一ddせずにファイルを開くことができます切り捨てまたは追加、またはシェルからのシークより複雑な例)。

    # 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
    

だから…システムツールとしては、ddほとんど役に立たない。テキスト(またはバイナリファイル)処理ツールとして、非常に価値があります!


私はそれが他の答えの要点を説明すると思うので受け入れられました(truncそしてseekから使用可能ですdd)。
kizzx2

2
もう1つの特別な用途:ddstdioバッファリングにより未読データを破壊する可能性なしに、シークできないファイル記述子からバイナリデータを読み取ることができます。例えばここを参照してください:etalabs.net/sh_tricks.html
R ...

2
@R ..:はい。GNU coreutils 6.10では、Nを超えてhead -c N呼び出すreadことはありません。NetBSD5.1では、をhead -c呼び出しますgetc。FreeBSD 7.4では、をhead -c呼び出しますfread
ジル

1
また、Coreutils ddはO_DIRECT(など)をシェルスクリプトに公開しますが、これもユニークだと思います。
デロバート

1
Coreutils truncateでは、ファイルの切り捨てまたは拡張が可能であるため、dd
dcoles

22

このddコマンドには、catが対応できない多くのオプションが含まれています。おそらくあなたの使用例では、猫は実行可能な代替品ですが、ddの代替品ではありません。

1つの例はdd、全体ではなく何かの一部をコピーするために使用します。おそらく、デバイス上の既知の場所に基づいて、isoイメージの中央から一部のビットをリッピングしたり、ハードドライブからパーティションテーブルをリッピングしたい場合があります。ではdd、あなたが開始を指定することができ、停止してこれらのアクションを許可数量オプション。

これらのオプションはdd、粒度の細かいデータ操作に不可欠です。一方、cat*はファイルオブジェクト、デバイス、またはストリーム全体に対してのみ操作できます。

*コメントでGillesが指摘したように、cat他のツールと組み合わせて何かの部分を分離することは可能ですが、catそれでもオブジェクト全体で動作します。


5
dd実際には低レベルのデバイスとは何の関係もありません/dev。他のデバイスと同様にエントリが必要です。を使用してパーティション全体をコピーしcatたり、の一部をコピーできますtail +c $(($start+1)) | head -c $count
ジル

16
もちろん。;-)そしてcat | head | tail、最後の数MBを取得するために1.6 TBのディスクイメージをフィードすると、ディスクスピンアップは月を地球に近づけます。
カレブ

2
@Gilles申し訳ありませんが、「低レベル」という用語の使用は、デバイスではなくデバイス上のデータに言及しているものの、あまり良い意味ではないことを認識していました。おそらく「微調整されたデータ操作」は「低レベルのデータ操作」よりも優れているでしょう。
カレブ

21

誰もまだ作成するDDを使用することができることを言及していないスパースファイルをしかし、truncate同じ目的のために使用することができます。

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

これはほとんど瞬時であり、たとえばループバックファイルとして使用できる任意の大きなファイルを作成します。

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

良い点は、最初は単一のディスクスペースブロックのみを使用し、その後は必要に応じてのみ増加することです(10 GBファイルのext4フォーマットはシステムで291 MBを消費します)。使用du-どのくらいのディスク容量が実際に使用されて見にlsファイルがに成長する可能性の報告のみ最大サイズ。


4
ls -lsスパースサイズを表示します。
jmtd

2
コマンドはファイルに無駄なバイトを書き込みます。dd of=sparse-file bs=1 count=0 seek=10Gはと同等truncate -s 10GB sparse-fileです。紛らわしいことに十分な、truncateddは正反対の解釈持ってGB対をG...
frostschutz

5
@frostschutz:man dd言う:MB =1000*1000, M =1024*1024など。そしてman truncate言う:MB 1000*1000, M 1024*1024違いはありません。私は両方を使用ddしてtruncateのGNU coreutilsのから。あなたもそうするべきです!:-)
エリック

@erik:修正してくれてありがとう。最近変更されていない場合は、他の何かと混同しているに違いありません。
frostschutz

10

ハードドライブの特定のセグメントを何かで上書きするのが一般的な例です。たとえば、次のコマンドを使用してMBRを削除できます。

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

また、空のファイルを作成できます(ループディスクイメージの場合など)。

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

余談ですが、この2番目のコマンドは、10 MBを使用するために知っている最速の方法です
ケビンM

3
@ケビン:より速いhead -cベンチマークを共有してください!
ジル

9

ddは、ハードドライブまたはその他のストレージデバイスのブートセクタをバックアップし(dd if=/dev/sda of=boot_sector.bin bs=512 count=1)、後で書き換える(dd if=boot_sector.bin of=/dev/sda)のに非常に便利です。同様に、暗号化されたボリュームのヘッダーをバックアップするのに役立ちます。

catそれを実行するためにねじれる可能性がありますが、書き換え部分でそれを信頼しません。cat特定のバイト数の読み取り/書き込みのみを行うのは困難です。


5

私は最近、Linuxの歴史で初めて複数の100ギガバイトのパーティションのクローンを作成する必要がありました(cf cp -arまたはrsync何回も役立っています)。もちろん、私はdd「誰もがあなたがそれを使用していることを誰もが知っているので...パフォーマンスに驚いた」と言った。少しのグーグルですぐに私はに行きましたがddrescue、これを数回使ったことがあり、見事に動作します(ddよりはるかに高速です)。


1
ddrescue特に障害のあるディスクからデータを取得するのに最適です。
-ryenus

5

ここに私が長年にわたって思いついたいくつかのDDのトリックがあります。

非友好的なttyまたは非インタラクティブモードbashでのカットアンドペースト

EOF / ^ D / ^ Fが検出されない場合は、ddを使用してテキストファイルをホストに転送できます。指定されたバイト数の後に自動的に読み込みを停止するため。

昨年と同じように、リモートホストで非ttyシェルを取得でき、ファイルを転送する必要があるセキュリティ演習中にこれを使用しました。

実際、base64でエンコードし、低速で信頼性の高い純粋なbash base64デコードスクリプトを使用して、いくつかのバイナリファイルを作成しました。

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

非常にクールなトリックは、ddの実行中にUSR1シグナルを送信すると、現在のステータス(読み取りバイト、1秒あたりのバイト数)を送信することです。

ユニバーサルスループット状態フィルター

これは、stdoutを介してデータを出力するプログラムの純粋なbash進行フィルターとして機能するように作成しました。(注:ほとんど何でもstdoutを介してデータを出力します-そうしないプログラムでは、/ dev / stdoutをファイル名として使用して、あなたに邪魔をしない場合はごまかすことができます。しかし、基本的には、Xを取得するたびにバイト数、ハッシュマークの印刷(ハッシュモードをオンにしたときの古い学校のFTPなど)

(注)プログレスファイルは不完全であり、これはほとんど概念実証でした。やり直した場合は、変数を使用するだけです。

 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

匿名シェルファイルハンドルを使用したスライスアンドダイスファイル

匿名ファイルハンドルを介してtar入力を提供することにより、エラーなしで抽出できる署名済みtarファイルを、どのようにtmpファイルを使用して部分的なファイルデータを保存することなく取得できるかを示す非常に擬似的なコード例を次に示します。

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

tl; drは次のとおりです。ddは非常に便利です。そして、これらは私の頭上から考えることができる3つの例にすぎません。


4

一部の出力コンテンツをリダイレクトできます。あなたが書く必要がある場合、それは特に便利ですsudo

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

それに加えsudoて:

echo some_content > output.txt

またはこれに:

echo some_content | sudo tee output.txt > /dev/null

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.