UNIX/Linuxの部屋 コマンド:dd

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




コマンド dd ファイルのコピー・ディスクダンプ・バックアップ・リストア・ファイル作成 このエントリーをはてなブックマークに追加

最終更新


dd コマンドは入力から出力へデータをコピーするコマンドである。cp コマンドはファイルからファイルにコピーするだけであるが、dd コマンドはファイルからデバイス、デバイスからファイル、デバイスからデバイスへのコピーも可能なため、ディスクのバックアップやダンプにも使用できる。



デバイス・ディスクのコピー
# dd if=/dev/ad0 of=/dev/ad1
⇒ /dev/ad0 を /dev/ad1 にコピーする。ただし両方のディスクが同容量でなくてはならない。

フロッピーのコピーなども可能。
# dd if=/dev/rfd0 of=fdd.flp
⇒ FDD の内容をファイルにダンプ
# dd if=kern.flp of=/dev/rfd0
⇒ フロッピーのイメージファイルを FDD にコピー。OS インストールフロッピー作成時によく使う。

ディスクのバックアップとリストア
バックアップやリストアは、シングルユーザモードに落とすか、デバイスを umount してから行うこと。
# dd if=/dev/ad0 of=ad0backup.dump
⇒ HDD からファイルへのバックアップ
# dd if=ad0backup.dump of=/dev/ad0
⇒ リストアは、バックアップのときと if・of を逆にする
データ量が大きいときは gzip で圧縮することもできる。
# dd if=/dev/ad0 | gzip -c > ad0backup.dump.gz
⇒ 圧縮しつつバックアップ
# gzip -dc < ad0backup.dump.gz | dd of=/dev/ad0
⇒ 伸長しつつリストア
ネットワーク越しのバックアップ
# tar cf - . | rsh remotehost dd of=/dev/テープデバイス名 obs=20b

ファイルのバックアップとリストア
ディスクだけでなく、ファイル単位でもバックアップできる。とはいえ 1ファイルだけバックアップしていても、あまりうれしくない。
# dd if=sample.txt of=/dev/ad0
⇒ sample.txt を HDD にバックアップ
# dd if=/dev/ad0 of=.cshrc
⇒ sample.txt を HDD からリストア

ファイル作成
dd コマンドで指定サイズのファイル作成も可能である。例えば /dev/zero を入力ファイルに指定することで、全データが NULL のファイルが生成できる。ファイルサイズは「count で指定したブロック数×ブロックサイズ」となる。デフォルトのブロックサイズは 512 だが、bs パラメータで変更可能。
% dd if=/dev/zero of=zero.dat count=1000
⇒ 512*1000 バイトの zero.dat が生成される
% dd if=/dev/zero of=zero.dat count=2048 bs=1
⇒ ブロックサイズを 1 に指定。2048 バイトの zero.dat が生成される

Solaris でファイル生成をするなら、mkfile コマンドを使ってもよい。

seek パラメータを指定することで、穴あきファイルを生成することもできる。
% dd if=/dev/zero of=sparse.dat bs=1024 seek=10 count=1
⇒ ブロックサイズ 1024 バイトで、ブロック10個分シークし、その後 1ブロック分を /dev/zero からコピーする

主要オプション一覧
if=[ファイル] 入力ファイル (デバイス)。指定しないと標準入力。
of=[ファイル] 出力ファイル (デバイス)。指定しないと標準出力。
bs=[サイズ] 入出力のブロックサイズを指定。ibs と obs の両方に同じ値をセットする場合に使用する。
ibs=[サイズ] 入力のブロックサイズを指定
obs=[サイズ] 出力のブロックサイズを指定
count=[ブロック数] コピーするブロック数を指定
conv=変換オプション 変換オプションを指定 (後述)。conv=hoge,fuga などと複数指定も可能。
seek=[ブロック数] 出力の開始位置を指定されたブロックに移動してからコピーする
oseek=[ブロック数] FreeBSD では seek と同じ。Solaris では違うっぽい…?
skip=[ブロック数] 入力の開始位置を指定されたブロックに移動してからコピーする
iseek=[ブロック数] FreeBSD では skip と同じ。Solaris では skip より速いと書いてある…?

サイズには数字のほか、k・m・g などの単位を指定できる (ブロック数にも使えるけど混乱するかも)。
bs=1 1バイト
bs=1b 512バイト (b はバイトではなくブロック)
bs=1k 1KB
bs=1m 1MB
bs=1g 1GB

conv に指定できる変換オプションうち、主要なものを以下にあげる。
◯noerror
HDD 読み取りエラーなど、入力でエラーが発生した場合でも終了せずに処理を続行する。noerror を指定しないと、dd はエラー発生時にすぐ終了してしまう。noerror を指定する場合は、必ず sync も指定すること (conv=noerror,sync)。これにより、エラーの部分は NULL で埋められて出力にコピーされる。sync を付けないとエラー部分は出力されない。また、noerror 指定時は count を明示的に指定すること (終端に達しても止まらなくなるらしい)。

◯sync
入力ブロックを、入力バッファサイズになるように NULL でパディングする。

◯notrunc
既に out.dat が存在し、ファイルサイズが 2048 バイトだったとする。この状態で
% dd if=/dev/zero of=out.dat count=1 bs=512
とすると、out.dat のファイルサイズは 512 バイトに切り詰められてしまう。一方、
% dd if=/dev/zero of=out.dat count=1 bs=512 conv=notrunc
と conv=notrunc を付けると、out.dat の先頭 512 バイトが NULL で埋められるが、513〜2048 バイト目までは最初のファイルの状態のまま残される。

コピー対象のサイズは「ブロックサイズ×ブロック数」で決まるため、以下のそれぞれのコマンドで生成されるファイル内容は全く同じであるが、ブロックサイズが小さすぎると時間がかかってしまうことに注意。
% dd if=/dev/zero of=zero.dat bs=1 count=51200000
⇒ 実行時間 3秒
% dd if=/dev/zero of=zero.dat bs=512 count=100000
⇒ 実行時間 2.5秒
% dd if=/dev/zero of=zero.dat bs=51200000 count=1
⇒ 実行時間 13分

なお、この例では入力がファイルであるためブロックサイズはどんな値でも (速度以外は) 問題ないが、入力がデバイスの場合は適切な値に設定する必要がある。ブロックデバイスの場合、ブロックサイズはセクタサイズの整数倍でなくてはならない (という表現であっているのだろうか)。
% dd if=/dev/ad0 of=ad0-backup.dump bs=1
dd: /dev/ad0: Invalid argument
⇒ 小さすぎてもエラー
% dd if=/dev/ad0 of=ad0-backup.dump bs=513
dd: /dev/ad0: Invalid argument
⇒ 大き過ぎてもエラー
% dd if=/dev/ad0 of=ad0-backup.dump bs=512
⇒ 1セクタ=512 バイトなので、OK
% dd if=/dev/ad0 of=ad0-backup.dump bs=1024
⇒ 整数倍なので OK
% dd if=/dev/ad0 of=ad0-backup.dump bs=8192
⇒ これも OK。一気に読み込むので、bs=512, bs=1024 より速いかもしれない
上記の bs=1 の例でエラーになるのは、そもそも /dev/ad0 に対する 1バイト分の read(2) がエラーとなるからである (Invalid Argument)。

また、「conv=noerror,sync」を指定した場合は、ブロックサイズを最小のセクタ単位で指定した方がよいとか。エラーが発生したブロックのみ NULL で埋められるらしい。
% dd if=/dev/ad0 of=zero.dat bs=512 count=.... conv=noerror,sync
⇒ 1セクタのみエラーになる場合は 512 バイトだけ NULL 埋めされる (のか?)
% dd if=/dev/ad0 of=zero.dat bs=1024 count=.... conv=noerror,sync
⇒ 動きはするが、お勧めしない。1セクタのみエラーになる場合でも、1024 バイトが NULL 埋めされてしまう (ということか?)

SIGINFO による状態通知
FreeBSD の dd は SIGINFO シグナルを受けると、現在の状態を表示する (処理はそのまま続行する)。
% dd if=/dev/zero of=zero.dat count=10000000
(処理中なので何も表示されないが、ここで Ctrl-t を押して SIGINFO を飛ばす)
load: 0.05 cmd: dd 5500 [running] 0.06u 0.93s 0% 564k
47717+0 records in
47717+0 records out
24431104 bytes transferred in 1.235103 secs (19780622 bytes/sec)
⇒ 入力・出力レコード数・バイト数などの情報が表示され、さらに処理は続く
(再度 Ctrl-t)
load: 0.12 cmd: dd 5500 [running] 0.12u 3.00s 0% 588k
145009+0 records in
145008+0 records out
74244096 bytes transferred in 3.606494 secs (20586225 bytes/sec)
⇒ 実行中であれば何度でも Ctrl-t で最新の状態を表示できる

余談
dd コマンドの機能は「convert and copy a file」なので本当は cc コマンドにしたかったが、既に C コンパイラが cc という名前を使っていたので、仕方なく cc の次の dd にしたらしい。
>> Linuxオンラインマニュアル(man) Linux dd(1)
>> Solaris10オンラインマニュアル(man) Solaris10 dd(1M)
>> FreeBSDオンラインマニュアル(man) FreeBSD dd(1)

読み方 dd (UNIXコマンド) [でぃー・でぃー] [でー・でー] このエントリーをはてなブックマークに追加

米国のユーザグループ UniForum が発行している機関誌 CommUNIXations(May/ June 1989) からの転載ということで、JUS の /etc/wall No.8/1990/May に載っていた「UNIX Trivia -- UNIX に関するクイズ100問」によると、名前の由来は、"Convert and Copy" の略で cc としたかったが、既にそれは存在していたので dd になったとういうことである。そのほかにも、単純に "Dump Data", "Disk Dumper", "Dump Disk" の略という説や IBM 汎用機の JCL にある DD 文 ("Data Definition" あるいは "Dataset Definition" の略)からきているという説もある。

[2019年11月追記] C言語や UNIX を開発したデニス・リッチーの 2004年の発言によると、「dd はJCL の DD が由来である」とのこと。
JCL の DD とは何かについて当ページ管理人は知識を持っていないが、下記が参考になるかもしれない。