dd

提供: ArchWiki
2022年10月7日 (金) 13:12時点におけるAshMyzk (トーク | 投稿記録)による版 (→‎MBR のバックアップと復元: 同期)
ナビゲーションに移動 検索に移動

関連記事

dd はファイルの変換とコピーを主な目的とする コアユーティリティ です。

cp と同様にデフォルトでは dd はファイルのビットごとのコピーを作成しますが、低レベルの I/O フロー制御機能を備えています。

詳細は、dd(1) またはフルドキュメントを参照してください。

ヒント: デフォルトでは、dd はタスクが完了するまで何も出力しません。操作の進行状況を監視するには、コマンドに status=progress オプションを追加します。
警告: この種のコマンドはどれも、データを不可逆的に破壊する可能性があるため、dd の使用には細心の注意を払う必要があります。

インストール

dd は GNU coreutils の一部です。このパッケージ内の他のユーティリティについては、Core utilities を参照してください。

ディスクの複製と復元

dd コマンドはシンプルでありながら多機能で強力なツールです。ファイルシステムの種類や OS に関係なく、コピー元からコピー先へブロック単位でコピーすることができます。ライブ CD のようなライブ環境から dd を使用するのが便利です。

警告: このタイプのコマンドと同様に使用時には十分な注意が必要です。さもないと、データが破壊される可能性があります。入力ファイル (if=) と出力ファイル (of=) の順番を覚えておいて、逆にしないでください。出力先のドライブやパーティション (of=) のサイズが、入力元 (if=) と同じかそれ以上である事を常に確認してください。

パーティションの複製

物理ディスク /dev/sda のパーティション 1 から、物理ディスク /dev/sdb のパーティション 1 へ:

# dd if=/dev/sda1 of=/dev/sdb1 bs=64K conv=noerror,sync status=progress
ノート: 出力パーティション of= (この例では sdb1) が存在しない場合、dd はこの名前のファイルを作成し、ルートファイルシステムをいっぱいにしてしまうので注意が必要です。

ハードディスク全体の複製

物理ディスク /dev/sda から物理ディスク /dev/sdb へ:

From physical disk /dev/sda to physical disk /dev/sdb:

# dd if=/dev/sda of=/dev/sdb bs=64K conv=noerror,sync status=progress

MBR (つまりブートローダ)、すべてのパーティション、UUID、データを含むドライブ全体のクローンを作成します。

  • bs= はブロックサイズを設定します。デフォルトは512バイトで、これは1980年代前半以降のハードドライブの「古典」的なブロックサイズですが、最も便利なものではありません。64KBや128KBなど、より大きな値を使用してください。また、「ブロックサイズ」だけでなく、読み取りエラーの伝搬にも影響を与えるため、以下の警告をお読みください。詳細は、[1][2] を参照して、自分の使用例に最適な bs 値を見付けてください。
  • noerror はすべての読み取りエラーを無視して操作を続けるように dd に指示します。dd のデフォルトの動作は、いかなるエラーでも停止します。
  • sync は読み込みエラーがあった場合、入力ブロックをゼロで埋め、データのオフセットは同期されたままになります。
  • status=progress は、操作がいつ完了するかを推測するために使用できる転送統計を表示します。
ノート: 指定するブロックサイズは、読み取りエラーの処理方法に影響します。以下をお読みください。データの回復には、ddrescue を使います。

dd ユーティリティには、技術的に「入力ブロックサイズ」(IBS)と「出力ブロックサイズ」(OBS)があります。bs を設定すると、実質的に IBS と OBS の両方を設定することになります。通常、ブロックサイズが例えば 1MiB の場合、dd は 1024×1024 バイトを読み込み、同じバイト数を書き込みます。しかし、読み取りエラーが発生すると、事態はおかしくなります。多くの人は、noerror,sync オプションを使うと、dd が「読み込みエラーをゼロで埋める」と思っているようですが、そうではありません。dd はドキュメントによると、読み込み完了後に OBS から IBS のサイズを埋める、つまりブロックの最後にゼロを追加するのです。つまり、ディスクの場合、512 バイトの読み取りエラーが読み取りの最初に1回発生しただけで、事実上 1MB 全体がめちゃくちゃになってしまうのです: 12ERROR89 は 120000089 ではなく 128900000 となります。

ディスクにエラーがないことが確認できれば、ブロックサイズを大きくしてコピーを進めることができ、コピーの速度が数倍向上します。例えば、Celeron 2.7GHz のシステムで、bs を 512 から 64K に変更すると、コピー速度が 35MB/s から 120MB/s になります。ただし、コピー元のディスクで発生した読み取りエラーは、コピー先のディスクではブロックエラーとして発生することに注意してください。

ヒント: dd の進行状況を表示するためには、status=progress オプションを使用してください。詳細については、dd(1) を参照してください。
ノート:
  • ext2/3/4 ファイルシステムの一意の UUID を取り戻すには、すべてのパーティションで、tune2fs /dev/sdXY -U random を使用します。スワップパーティションの場合は、代わりに、mkswap /dev/sdXY を使ってください。
  • dd によるパーティションテーブルの変更はカーネルには登録されません。再起動せずに変更を通知するには、partprobe (GNU Parted の一部)のようなユーティリティを使ってください。

パーティションテーブルのバックアップ

fdisk#パーティションテーブルのバックアップとリストア または gdisk#パーティションテーブルのバックアップとリストア を参照。

Create disk image

Boot from a live medium and make sure no partitions are mounted from the source hard drive.

Then mount the external hard drive and backup the drive:

# dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c  > /path/to/backup.img.gz

If necessary (e.g. when the resulting files will be stored on a FAT32 file system) split the disk image into multiple parts (see also split(1)):

# dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c | split -a3 -b2G - /path/to/backup.img.gz

If there is not enough disk space locally, you may send the image through ssh:

# dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c | ssh user@local dd of=backup.img.gz

Finally, save extra information about the drive geometry necessary in order to interpret the partition table stored within the image. The most important of which is the cylinder size.

# fdisk -l /dev/sda > /path/to/list_fdisk.info
ノート: You may wish to use a block size (bs=) that is equal to the amount of cache on the HD you are backing up. For example, bs=8192K works for an 8 MiB cache. The 64 KiB mentioned in this article is better than the default bs=512 bytes, but it will run faster with a larger bs=.
ヒント: gzip is only able to compress data using a single CPU core, which leads to a data throughput considerably lower than the write speeds on modern storage. In order to leverage multicore compression and create a disk image more quickly, one could for instance install the pigz package, and simply replace the gzip -c command above with pigz -c. For large disks, this can potentially save hours.

システムの復元

システムを復元するには:

# gunzip -c /path/to/backup.img.gz | dd of=/dev/sda

イメージが分割されている場合は、代わりに以下を使用してください:

# cat /path/to/backup.img.gz* | gunzip -c | dd of=/dev/sda

バイナリーファイルのパッチ適用

ファイルのオフセット 0x123AB を16進数列 FF C0 14 に置き換えたい場合は次のコマンドラインで実行できます:

# printf '\xff\xc0\x14' | dd seek=$((0x123AB)) conv=notrunc bs=1 of=/path/to/file

MBR のバックアップと復元

ディスクに変更を加える前に、ドライブのパーティションテーブルとパーティションスキームをバックアップしておくと良いでしょう。また、同じパーティションレイアウトを複数のドライブにコピーするためにバックアップを使うこともできます。

MBR はディスクの先頭 512 バイトに格納されています。MBR は4つの部分から成ります:

  1. 始めの 440 バイトにはブートストラップコード (ブートローダ) が含まれています。
  2. 次の 6 バイトにはディスクのシグネチャが含まれています。
  3. 次の 64 バイトにはパーティションテーブルが含まれています (各16バイトの4つのエントリ、各プライマリパーティションに1つのエントリ)。
  4. 最後の 2 バイトにはブートシグネチャが含まれています。

MBR を mbr_file.img として保存するには:

# dd if=/dev/sdX of=/path/to/mbr_file.img bs=512 count=1

完全な dd ディスクイメージから MBR を取り出すこともできます:

# dd if=/path/to/disk.img of=/path/to/mbr_file.img bs=512 count=1

バックアップから MBR を復元するには (注意。このコマンドは既存のパーティションテーブルを破壊し、ディスク上のすべてのデータにアクセスできなくなります):

# dd if=/path/to/mbr_file.img of=/dev/sdX bs=512 count=1
警告: 一致しないパーティションテーブルを使って MBR を復元すると、データを読み出せなくなり、ほぼ復元不可能になります。ブートローダを再インストールしたいだけならば、ブートローダは DOS 互換領域も実装しているので、そのブートローダの関連するページを見てください: GRUBSyslinux

ブートローダを復元したいだけで、プライマリパーティションテーブルのエントリに興味はないならば、単に MBR の先頭 440 バイトを復元すれば良いだけです:

# dd if=/path/to/mbr_file.img of=/dev/sdX bs=440 count=1

パーティションテーブルだけを復元するには、以下のコマンドを使う必要があります:

# dd if=/path/to/mbr_file.img of=/dev/sdX bs=1 skip=446 count=64

ブートローダーの削除

MBR ブートスラップコードを消去するには(別のオペレーティングシステムを完全に再インストールする必要がある場合に役立つ場合があります)、最初の440バイトのみをゼロにする必要があります:

# dd if=/dev/zero of=/dev/sdX bs=440 count=1

Troubleshooting

この記事あるいはセクションで使われている用語や表現には問題が存在します。
議論: The troubleshooting section currently only hold one subsection that describes the logic of dd's count option. Merge this into a previous section for a better overall reading experience in linear order. (議論: トーク:Dd#)

Partial read: copied data is smaller than requested

Files created with dd can end up with a smaller size than requested if a full input block is not available for various reasons (i.e. the underlying read(2) system call returns early.) This can happen when reading from a pipe(7), or when reading a device file like /dev/urandom and /dev/random (e.g. due to hardcoded limitation of underlying kernel device driver or insufficient entropy.), in conjunction of count=n option where n is the number of input block(s) to copy to output.

It is possible, but not guaranteed, that dd will warn you about such kind of issue:

dd: warning: partial read (X bytes); suggest iflag=fullblock

The solution is to do as the warning says, add iflag=fullblock option in addition to the input file option to the dd command. For example, to create a new file filled up with random data in total length of 40 megabytes:

$ dd if=/dev/urandom of=new-file-filled-by-urandom.bin bs=40M count=1 iflag=fullblock
ノート: When reading from a pipe or a special device file like we just mentioned below for copying a portion of file in a fixed length with count=n option being specified, it is suggested to, or always strongly recommended to add the iflag=fullblock option to the dd command if in case of wiping a portion of device or file.

When reading from a pipe, an alternative to iflag=fullblock is to limit bs to the PIPE_BUF constant value as defined in linux/limits.h to make the pipe(7) I/O atomic. For example, to prepare a text file filled up will random alphanumeric string in total length of 5 megabytes:

$ LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | dd of=passtext-5m.txt bs=4k count=1280

Since the output file is not a pipe, one may prefer to use ibs and obs options to set block size separately for the (input) pipe and the (output) on-disk file. For example, to set a more efficient block size for output file:

$ LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | dd of=passtext-5m.txt ibs=4k obs=64k count=1280
ヒント: In some circumstances, merely keep the the output block size the same the value as input block size with a value defined by PIPE_BUF constant may already be optimal.