「Dd」の版間の差分
(冒頭を同期) |
(参照を翻訳して追加) |
||
(3人の利用者による、間の19版が非表示) | |||
25行目: | 25行目: | ||
== インストール == |
== インストール == |
||
− | ''dd'' は GNU {{Pkg|coreutils}} の一部です。パッケージ内の他のユーティリティについては、[[Core utilities]] を参照してください。 |
+ | ''dd'' は GNU {{Pkg|coreutils}} の一部です。このパッケージ内の他のユーティリティについては、[[Core utilities]] を参照してください。 |
== ディスクの複製と復元 == |
== ディスクの複製と復元 == |
||
− | ''dd'' コマンドはシンプルでありながら多機能で強力なツールです。ファイルシステムの種類や OS に関係なくコピー元からコピー先へブロック単位でコピーすることができます。ライブ CD のようなライブ環境から ''dd'' を使用するのが便利です。 |
+ | ''dd'' コマンドはシンプルでありながら多機能で強力なツールです。ファイルシステムの種類や OS に関係なく、コピー元からコピー先へブロック単位でコピーすることができます。ライブ CD のようなライブ環境から ''dd'' を使用するのが便利です。 |
− | {{Warning|このタイプのコマンドと同様に使用時には十分な注意が必要です。データが破壊される可能性があります。入力ファイル ({{ic|1=if=}}) と出力ファイル ({{ic|1=of=}}) の順番を覚えておいて、逆にしないでください。出力先のドライブやパーティション ({{ic|1=of=}}) のサイズが、入力元 ({{ic|1=if=}}) と同じかそれ以上である事を常に確認してください。 |
+ | {{Warning|このタイプのコマンドと同様に使用時には十分な注意が必要です。さもないと、データが破壊される可能性があります。入力ファイル ({{ic|1=if=}}) と出力ファイル ({{ic|1=of=}}) の順番を覚えておいて、逆にしないでください。出力先のドライブやパーティション ({{ic|1=of=}}) のサイズが、入力元 ({{ic|1=if=}}) と同じかそれ以上である事を常に確認してください。 |
}} |
}} |
||
40行目: | 40行目: | ||
# dd if=/dev/sda1 of=/dev/sdb1 bs=64K conv=noerror,sync status=progress |
# dd if=/dev/sda1 of=/dev/sdb1 bs=64K conv=noerror,sync status=progress |
||
− | {{Note|出力パーティション {{ic|1=of=}} (例では {{ic|sdb1}}) が存在しない場合、''dd'' はこの名前のファイルを作成し、ルートファイルシステムをいっぱいにしてしまうので注意が必要です。}} |
+ | {{Note|出力パーティション {{ic|1=of=}} (この例では {{ic|sdb1}}) が存在しない場合、''dd'' はこの名前のファイルを作成し、ルートファイルシステムをいっぱいにしてしまうので注意が必要です。}} |
=== ハードディスク全体の複製 === |
=== ハードディスク全体の複製 === |
||
物理ディスク {{ic|/dev/sda}} から物理ディスク {{ic|/dev/sdb}} へ: |
物理ディスク {{ic|/dev/sda}} から物理ディスク {{ic|/dev/sdb}} へ: |
||
− | |||
− | From physical disk {{ic|/dev/sda}} to physical disk {{ic|/dev/sdb}}: |
||
# dd if=/dev/sda of=/dev/sdb bs=64K conv=noerror,sync status=progress |
# dd if=/dev/sda of=/dev/sdb bs=64K conv=noerror,sync status=progress |
||
− | + | このコマンドは、パーティションテーブル、ブートローダー、すべてのパーティション、UUID、データを含むドライブ全体を複製します。 |
|
− | * {{ic|1=bs=}} はブロックサイズを設定します。デフォルトは512バイトで、これは1980年代前半以降のハードドライブの「古典」的なブロックサイズですが、最も便利なものではありません。64KBや128KBなど、より大きな値を使用してください。また、「ブロックサイズ」だけでなく、読み取りエラーの伝搬にも影響を与えるため、 |
+ | * {{ic|1=bs=}} はブロックサイズを設定します。デフォルトは512バイトで、これは1980年代前半以降のハードドライブの「古典」的なブロックサイズですが、最も便利なものではありません。64KBや128KBなど、より大きな値を使用してください。また、「ブロックサイズ」だけでなく、読み取りエラーの伝搬にも影響を与えるため、下記の警告をお読みください。詳細は、[https://www.mail-archive.com/eug-lug@efn.org/msg12073.html] と [http://blog.tdg5.com/tuning-dd-block-size/] を参照して、最適な bs 値を見つけてください。 |
* {{ic|noerror}} はすべての読み取りエラーを無視して操作を続けるように ''dd'' に指示します。''dd'' のデフォルトの動作は、いかなるエラーでも停止します。 |
* {{ic|noerror}} はすべての読み取りエラーを無視して操作を続けるように ''dd'' に指示します。''dd'' のデフォルトの動作は、いかなるエラーでも停止します。 |
||
− | * {{ic|sync}} は読み込みエラーがあった場合、入力ブロックをゼロで埋め、データのオフセットは同期されたままになります。 |
+ | * {{ic|sync}} は読み込みエラーがあった場合、入力ブロックをゼロで埋め、データのオフセットは同期されたままになります (読み込みエラーが疑われる場合、sync を用いた際の読み込みエラーの挙動に関する下記の詳細な説明を見てください)。 |
* {{ic|1=status=progress}} は、操作がいつ完了するかを推測するために使用できる転送統計を表示します。 |
* {{ic|1=status=progress}} は、操作がいつ完了するかを推測するために使用できる転送統計を表示します。 |
||
− | {{Note|指定するブロックサイズは、読み取りエラーの処理方法に影響します。以下をお読みください。データの回復には、[[ディスクのクローン#ddrescue を使う|ddrescue]] を使い |
+ | {{Note|指定するブロックサイズは、読み取りエラーの処理方法に影響します。以下をお読みください。データの回復には、[[ディスクのクローン#ddrescue を使う|ddrescue]] を使用してください。}} |
− | ''dd'' ユーティリティには、技術的に「入力ブロックサイズ」 |
+ | ''dd'' ユーティリティには、技術的には「入力ブロックサイズ」(IBS)と「出力ブロックサイズ」(OBS)があります。{{ic|bs}} を設定すると、実質的に IBS と OBS の両方を設定することになります。通常、ブロックサイズが例えば 1MiB の場合、dd は 1024×1024 バイトを読み込み、同じバイト数を書き込みます。しかし、読み取りエラーが発生すると、事態はおかしくなります。多くの人は、{{ic|noerror,sync}} オプションを使うと、dd が「読み込みエラーをゼロで埋める」と思っているようですが、そうではありません。ドキュメントによると、dd は読み込み完了後に OBS から IBS のサイズを埋める、つまりブロックの最後にゼロを追加するのです。つまり、ディスクの場合、512 バイトの読み取りエラーが読み取りの最初に1回発生しただけで、事実上 1MB 全体がめちゃくちゃになってしまうのです: 12ERROR89 は 120000089 ではなく 128900000 となります。 |
− | ディスクにエラーがないことが確認できれば、ブロックサイズを大きくしてコピーを進めることができ、コピーの速度が数倍向上します。例えば、Celeron 2.7GHz のシステムで、bs を 512 から 64K に変更すると、コピー速度が 35MB/s から 120MB/s になります。ただし、コピー元のディスクで発生した読み取りエラーは、コピー先のディスクではブロックエラーとして発生することに注意してください。 |
+ | ディスクにエラーがないことが確認できれば、ブロックサイズを大きくしてコピーを進めることができ、コピーの速度が数倍向上します。例えば、Celeron 2.7GHz のシステムで、bs を 512 から 64K に変更すると、コピー速度が 35MB/s から 120MB/s になります。ただし、コピー元のディスクで発生した読み取りエラーは、コピー先のディスクではブロックエラーとして発生することに注意してください。つまり、512バイトのリードエラーは、出力先の 64 KiB ブロック全体をめちゃくちゃにします。 |
{{Tip|''dd'' の進行状況を表示するためには、{{ic|1=status=progress}} オプションを使用してください。詳細については、{{man|1|dd}} を参照してください。}} |
{{Tip|''dd'' の進行状況を表示するためには、{{ic|1=status=progress}} オプションを使用してください。詳細については、{{man|1|dd}} を参照してください。}} |
||
{{Note| |
{{Note| |
||
− | * ''ext2/3/4'' ファイルシステム |
+ | * ''ext2/3/4'' ファイルシステムの UUID を一意な状態に戻すには、すべてのパーティションで、{{ic|tune2fs /dev/sd''XY'' -U random}} を使用してください。スワップパーティションの場合は、代わりに、{{ic|mkswap -U random /dev/sd''XY''}} を使ってください。 |
+ | * [[GPT]] ディスクを複製する場合、[[GPT fdisk#パーティションテーブルのバックアップとリストア|sgdisk]] を使うことで、ディスクとパーティションの GUID をランダム化し、GUID の一意性を保つことができます。 |
||
* ''dd'' によるパーティションテーブルの変更はカーネルには登録されません。再起動せずに変更を通知するには、''partprobe'' ([[GNU Parted]] の一部)のようなユーティリティを使ってください。 |
* ''dd'' によるパーティションテーブルの変更はカーネルには登録されません。再起動せずに変更を通知するには、''partprobe'' ([[GNU Parted]] の一部)のようなユーティリティを使ってください。 |
||
}} |
}} |
||
74行目: | 73行目: | ||
[[fdisk#パーティションテーブルのバックアップとリストア]] または [[gdisk#パーティションテーブルのバックアップとリストア]] を参照。 |
[[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'' |
# dd if=/dev/sda conv=sync,noerror bs=64K {{!}} gzip -c > ''/path/to/backup.img.gz'' |
||
+ | 必要であれば (出力ファイルが [[FAT32]] ファイルシステム上に保存される場合など)、ディスクイメージを複数に分けてください ({{man|1|split}} も見てください): |
||
− | 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 {{man|1|split}}): |
||
# dd if=/dev/sda conv=sync,noerror bs=64K {{!}} gzip -c {{!}} split -a3 -b2G - ''/path/to/backup.img.gz'' |
# dd if=/dev/sda conv=sync,noerror bs=64K {{!}} gzip -c {{!}} split -a3 -b2G - ''/path/to/backup.img.gz'' |
||
+ | ローカルに十分なディスクスペースがない場合、イメージを ''ssh'' を通して送ることもできます: |
||
− | 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 |
# 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'' |
# fdisk -l /dev/sda > ''/path/to/list_fdisk.info'' |
||
+ | {{Note|バックアップする HD のキャッシュの容量と同じブロックサイズ ({{ic|1=bs=}}) を使うと良いかもしれません。例えば、{{ic|1=bs=8192K}} は 8 MiB キャッシュでうまく行きます。この記事で説明されている 64 KiB は、デフォルトの {{ic|1=bs=512}} バイトよりも良いですが、より多くの {{ic|1=bs=}} を使えばより速く実行できます。}} |
||
− | {{Note|You may wish to use a block size ({{ic|1=bs=}}) that is equal to the amount of cache on the HD you are backing up. For example, {{ic|1=bs=8192K}} works for an 8 MiB cache. The 64 KiB mentioned in this article is better than the default {{ic|1=bs=512}} bytes, but it will run faster with a larger {{ic|1=bs=}}.}} |
||
+ | {{Tip|''gzip'' はデータ圧縮にシングルの CPU コアしか使用できません。そのせいで、データのスループットが最近のストレージの書き込みスピードよりかなり遅くなってしまいます。マルチコア圧縮でディスクイメージの作成をより速くするには、例えば {{Pkg|pigz}} などのパッケージをインストールし、上記の {{ic|gzip -c}} コマンドを {{ic|pigz -c}} に置き換えてください。巨大なディスクでは時間を節約できるかもしれません。また、他の圧縮アルゴリズム ({{Pkg|zstd}} など) を試しても良いかもしれません。}} |
||
− | {{Tip|''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 {{Pkg|pigz}} package, and simply replace the {{ic|gzip -c}} command above with {{ic|pigz -c}}. For large disks, this can potentially save hours.}} |
||
=== システムの復元 === |
=== システムの復元 === |
||
107行目: | 106行目: | ||
# cat ''/path/to/backup.img.gz*'' | gunzip -c | dd of=/dev/sda |
# cat ''/path/to/backup.img.gz*'' | gunzip -c | dd of=/dev/sda |
||
− | |||
− | == バイナリーファイルのパッチ適用 == |
||
− | |||
− | ファイルのオフセット {{ic|0x123AB}} を16進数列 {{ic|FF C0 14}} に置き換えたい場合は次のコマンドラインで実行できます: {{bc|1=# printf '\xff\xc0\x14' {{!}} dd seek=$((0x123AB)) conv=notrunc bs=1 of=''/path/to/file''}} |
||
== MBR のバックアップと復元 == |
== MBR のバックアップと復元 == |
||
+ | ディスクに変更を加える前に、ドライブのパーティションテーブルとパーティションスキームをバックアップしておくと良いでしょう。また、同じパーティションレイアウトを複数のドライブにコピーするためにバックアップを使うこともできます。 |
||
− | Before making changes to a disk, you may want to backup the partition table and partition scheme of the drive. You can also use a backup to copy the same partition layout to numerous drives. |
||
+ | MBR はディスクの先頭 512 バイトに格納されています。MBR は4つの部分から成ります: |
||
− | The MBR is stored in the the first 512 bytes of the disk. It consists of 4 parts: |
||
+ | # 始めの 440 バイトにはブートストラップコード (ブートローダ) が含まれています。 |
||
− | # The first 440 bytes contain the bootstrap code (boot loader). |
||
+ | # 次の 6 バイトにはディスクのシグネチャが含まれています。 |
||
− | # The next 6 bytes contain the disk signature. |
||
+ | # 次の 64 バイトにはパーティションテーブルが含まれています (各16バイトの4つのエントリ、各プライマリパーティションに1つのエントリ)。 |
||
− | # The next 64 bytes contain the partition table (4 entries of 16 bytes each, one entry for each primary partition). |
||
+ | # 最後の 2 バイトにはブートシグネチャが含まれています。 |
||
− | # The last 2 bytes contain a boot signature. |
||
− | + | MBR を {{ic|mbr_file.img}} として保存するには: |
|
# dd if=/dev/sd''X'' of=''/path/to/mbr_file.img'' bs=512 count=1 |
# dd if=/dev/sd''X'' of=''/path/to/mbr_file.img'' bs=512 count=1 |
||
+ | 完全な dd ディスクイメージから MBR を取り出すこともできます: |
||
− | You can also extract the MBR from a full dd disk image: |
||
# dd if=''/path/to/disk.img'' of=''/path/to/mbr_file.img'' bs=512 count=1 |
# dd if=''/path/to/disk.img'' of=''/path/to/mbr_file.img'' bs=512 count=1 |
||
+ | バックアップから MBR を復元するには (注意。このコマンドは既存のパーティションテーブルを破壊し、ディスク上のすべてのデータにアクセスできなくなります): |
||
− | To restore (be careful, this destroys the existing partition table and with it access to all data on the disk): |
||
# dd if=/''path/to/mbr_file.img'' of=/dev/sd''X'' bs=512 count=1 |
# dd if=/''path/to/mbr_file.img'' of=/dev/sd''X'' bs=512 count=1 |
||
+ | {{Warning|一致しないパーティションテーブルを使って MBR を復元すると、データを読み出せなくなり、ほぼ復元不可能になります。ブートローダを再インストールしたいだけならば、ブートローダは [https://www.pixelbeat.org/docs/disk/ DOS 互換領域]も実装しているので、そのブートローダの関連するページを見てください: [[GRUB]] や [[Syslinux]]。}} |
||
− | {{Warning|Restoring the MBR with a mismatching partition table will make your data unreadable and nearly impossible to recover. If you simply need to reinstall the bootloader see their respective pages as they also employ the [https://www.pixelbeat.org/docs/disk/ DOS compatibility region]: [[GRUB]] or [[Syslinux]].}} |
||
+ | ブートローダを復元したいだけで、プライマリパーティションテーブルのエントリに興味はないならば、単に MBR の先頭 440 バイトを復元すれば良いだけです: |
||
− | If you only want to restore the boot loader, but not the primary partition table entries, just restore the first 440 bytes of the MBR: |
||
# dd if=''/path/to/mbr_file.img'' of=/dev/sd''X'' bs=440 count=1 |
# dd if=''/path/to/mbr_file.img'' of=/dev/sd''X'' bs=440 count=1 |
||
+ | パーティションテーブルだけを復元するには、以下のコマンドを使う必要があります: |
||
− | To restore only the partition table, one must use: |
||
# dd if=''/path/to/mbr_file.img'' of=/dev/sd''X'' bs=1 skip=446 count=64 |
# dd if=''/path/to/mbr_file.img'' of=/dev/sd''X'' bs=1 skip=446 count=64 |
||
147行目: | 142行目: | ||
=== ブートローダーの削除 === |
=== ブートローダーの削除 === |
||
− | MBR ブートスラップコードを消去するには(別のオペレーティングシステムを完全に再インストールする必要がある場合に役立つ場合があります)、最初の440バイトのみをゼロにする必要があります |
+ | MBR ブートスラップコードを消去するには(別のオペレーティングシステムを完全に再インストールする必要がある場合に役立つ場合があります)、最初の440バイトのみをゼロにする必要があります: |
# dd if=/dev/zero of=/dev/sd''X'' bs=440 count=1 |
# dd if=/dev/zero of=/dev/sd''X'' bs=440 count=1 |
||
+ | == ディスク関連や他の使用場面 == |
||
− | == Troubleshooting == |
||
+ | 既にお気づきの方もいらっしゃるかもしれませんが、{{man|1|dd}} コアユーティリティは他のユーティリティと比較して [https://unix.stackexchange.com/a/12538#12538 かなり異なる] コマンドラインのシンタックスを持っています。さらに、[https://unix.stackexchange.com/a/12538#12538 他のコモディティユーティリティにはないユニークな機能] をサポートしていますが、特定のシナリオに適用すると、[https://www.pixelbeat.org/docs/coreutils-gotchas.html#dd あまり理想的でない] か[[dd#Partial_read:_copied_data_is_smaller_than_requested|potential error-prone]] デフォルト動作 (時には、できないこと) がいくつも存在します。そのため、ユーザーは ''dd'' コアユーティリティの代わりに、ある面ではより優れた代替品を使いたいと思うかもしれません。 |
||
− | === Partial read === |
||
+ | そうは言っても、''dd'' は [[coreutils|core utility]] であり、Arch や他の多くのシステムにデフォルトでインストールされているため、代替ユーティリティやより専門化されたユーティリティよりも好ましいことに注意する必要があります。システムに新しいパッケージをインストールするのは不便です。 |
||
− | Files created with ''dd'' can end up with a smaller size than requested if a full input block is not available and the {{man|2|read}} system call returns early. This can happen when reading from a {{man|7|pipe}} or when reading from {{ic|/dev/random}} and there is not enough entropy[https://unix.stackexchange.com/a/121888], or from {{ic|/dev/urandom}} when reading more than 32 MiB[https://unix.stackexchange.com/a/178957]. |
||
+ | 上記で説明した 2 つの側面をカバーするために、このセクションでは、他の汎用ユーティリティではほとんど見られない {{man|1|dd}} コア ユーティリティの機能を、[[Pacman/比較表]] の記事に似た形式で要約することに専念します。ただし、サンプルの量は、''dd'' のこれらの機能を調べるのに十分な量 (''ヒント:'' の ''ie'' または ''To'' 節で示されています) にできる限り少なく、単純に削減されています。サブセクションの下のボックス)、実践または疑似コードのいずれかにおいてです. |
||
− | It is possible, but not guaranteed, that ''dd'' will warn you about the issue: |
||
+ | |||
+ | {{note|この専用セクションを適切な長さに保つために、代替ユーティリティの比較には、公式リポジトリにあるパッケージのみが含まれています。この場合、言及されている他のユーティリティよりも明らかな利点があり、必要に応じて詳細が記載されています。<br>その他の代替ユーティリティについては、[[coreutils#dd の代替]] を参照して下さい。}} |
||
+ | |||
+ | === バイナリファイルにブロック単位のパッチをインプレースに適用する === |
||
+ | |||
+ | 自動シェルスクリプトで機能が限定されたバイナリファイルパッチャーとして ''dd'' を使用することは珍しいことではありません。これは、書き込み前に指定されたオフセットによって出力ファイルを {{ic|seek}} することができ、ブロックすることができるためです。 {{ic|1=conv=notrunc}} オプションを追加して、出力ファイルにブロック単位 (または {{ic|1=bs=1}} の場合はバイト y バイト) でインプレースパッチを適用します。 |
||
+ | |||
+ | たとえば、{{man|5|cpio|Portable ASCII Format}} アーカイブ内の最初のメンバーのタイムスタンプ部分を変更するには、ファイルの 49 番目のバイトから始まります (または、次の場合は {{ic|0x30}} のオフセットで始まります)。16 進表記を好む場合): |
||
+ | |||
+ | $ touch a-randomly-chosen-file |
||
+ | $ bsdtar -cf example-modify-ts.cpio --format odc -- a-randomly-chosen-file |
||
+ | |||
+ | $ printf '%011o' "$(date -d "2019-12-21 00:00:00" +%s)" | dd conv=notrunc of=example-modify-ts.cpio seek='''48''' oflag=seek_bytes |
||
+ | |||
+ | {{note|現在文書化されていない [https://github.com/coreutils/coreutils/commit/140eca15c4a3d3213629a048cc307fde0d094738 {{ic|seek_bytes}} 出力フラグ] は、出力への {{man|2|write}} を開始する前にブロックではなくバイトのオフセットで出力をシークするために上記に追加されています。}} |
||
+ | |||
+ | {{tip|コマンドライン入力の 16 進表記からバイト ストリームを出力するには、{{man|1|basenc|base16}} および/または {{man|1|printf}} を使用します。}} |
||
+ | |||
+ | {{tip|この機能では、''dd'' の代わりに、シェルが開いたファイルディスクリプタに対して {{man|2|lseek}} を呼び出すことをサポートするシェルを使用することを検討することができます。: |
||
+ | |||
+ | * ''dd'' の入力ファイルは {{man|2|splice}} システムコールを利用するプログラムと接続されたパイプであり、ユーザはより良いパフォーマンスのために ''dd'' の不必要なユーザ空間 I/O を避けたいと考えています。 |
||
+ | * または、シェルスクリプトのループ内で頻繁に {{man|2|fork}} が発生するのを避け、パフォーマンスペナルティを下げたい。 |
||
+ | |||
+ | その場合、まずそのシェルにファイルディスクリプタを開かせ、そのファイルディスクリプタに対してシーク操作を行い、{{man|2|splice}} システムコールを使う対応するユーティリティの出力端としてこのファイルディスクリプタを割り当てる必要があります(あるいは{{man|1|zshmodules|sysseek}} のようにフォークしないシェル内蔵コマンドもあります):{{hc|$ zsh|<nowiki>$ local +xr openToWriteFD |
||
+ | $ zmodload zsh/system |
||
+ | $ sysopen -wo cloexec -u openToWriteFD example-modify-ts.cpio |
||
+ | $ sysseek -u $openToWriteFD 48 |
||
+ | $ printf '%011o' "$(date -d "2019-12-21 00:00:00" +%s)" >&${openToWriteFD}</nowiki>}} |
||
+ | {{warning|オフセットを使用して書き込む必要があるプログラムが実際に {{man|2|splice}} を使用していることを確認できない場合は、このアプローチの使用を避けてください (これは、プログラムが出力に対していかなる種類のシークや切り捨ても実行しないことを意味します)。一部のプログラムは、この動作がコマンド ラインフラグで指定されていない場合でも、入力/出力ファイル記述子を自動的にシーク/切り捨てることがあります。これにより、シェルの {{man|3|lseek}} 呼び出しが無効になったり、開いているファイル記述子が予期せず切り詰められたりすることがあります。}}}} |
||
+ | |||
+ | === VFAT ファイルシステムイメージのボリュームラベルを表示する === |
||
+ | |||
+ | {{tip|この特定のシナリオでは、より現実的な選択肢は {{pkg|file}} です。}} |
||
+ | |||
+ | ファイルシステム [https://wiki.osdev.org/FAT#FAT_32_2 VFAT のボリュームラベル] イメージファイルを読み取るには、ASCII スペースが埋め込まれた全長 11 バイトで、オフセットは {{ic|0x047}} です。: |
||
+ | |||
+ | $ truncate -s ''33M'' empty-hole.img |
||
+ | $ fatlabel empty-hole.img LabelMe |
||
+ | |||
+ | $ dd iflag=skip_bytes,count_bytes count=11 skip=$((0x047)) if=empty-hole.img | sed -e 's% *$%%' |
||
+ | {{note|[https://github.com/coreutils/coreutils/commit/140eca15c4a3d3213629a048cc307fde0d094738 両方の入力フラグは現在文書化されていません]: |
||
+ | * 以前の {{ic|skip_bytes}} は、入力ファイルから {{man|2|read}} を開始する前に、ブロック数ではなくバイト数でオフセットしてシーク (シークできない入力の場合は ''skip'') するように ''dd'' に指示しました。 |
||
+ | * {{ic|count_bytes}} では、ブロック数ではなく、入力ファイルからコピーするブロックの総量を ''バイト'' で指定することができます。このオプションを指定しても部分的な {{man|2|read}} の対象となる可能性があるので混乱するかもしれませんが、この挙動をより理解するために [[dd#部分読み取り: コピーされたデータは要求されたデータよりも小さい|input block {{ic|count}}]] の小数値と考えるようにします。}} |
||
+ | |||
+ | {{tip|''指定された長さ内で入力 (オフセット付き) から出力にデータを転送するには''、シェル スクリプトでは、代わりに範囲表記を使用する代替手段として {{man|1|curl|r,}} を考慮することもできます。{{note|''curl'' は、入力ファイルがデバイス/パイプである場合のシーク/スキップをサポートしません。別の代替手段 {{man|1|socat}} は、入力ファイルに対するこれらの操作をサポートします (ブロックデバイスを含む、パイプを除く) 文字デバイス'') ですが、''curl'' ほどコモディティ化されていません。:{{bc|<nowiki>$ socat -u -,seek=$((0x047)),readbytes=11 - < empty-hole.img | sed -e 's% *$%%'</nowiki>}}}}}} |
||
+ | |||
+ | === パイプで繋がれたコマンド間で sponge する === |
||
+ | |||
+ | {{tip|タイトルですでに述べたように、この特定のシナリオでの実際的な選択肢は {{ic|<nowiki>${TMPDIR:-/tmp}</nowiki> への書き込みによるアトミック書き込みをサポートする {{man|1|sponge}} です}}}} |
||
+ | |||
+ | 次の例では、出力側のブロックが予想より長くなった場合に、入力側で不必要に長く続く TCP 接続を避けるために、2 つのコマンドの間に ''dd'' を挿入し、出力ブロックサイズは入力よりも確実に大きく、それでも使用可能なメモリよりはかなり小さいものにすることができます。 |
||
+ | |||
+ | $ curl -qgsfL <nowiki>http://example.org/mirrors/ftp.archlinux.org/mirrored.md5deep</nowiki> | dd ibs=128k obs=200M | ''poor-mirroring-script-that-perform-mirroring-on-input-paths-line-by-line-wo-buffer-entire-list-first'' |
||
+ | |||
+ | {{warning|''dd'' はコピー操作全体を開始する前に出力ファイルを切り詰めるため、これを {{man|1|sponge}} の一般的な代替手段として考慮しないでください。}} |
||
+ | |||
+ | === サイズの制限付きでデータを転送する === |
||
+ | |||
+ | データストリーミングのシェルスクリプトで ''dd'' を使用すると、パイプコマンドで消費されるデータの合計長を制限することができるのは一般的です。例えば、ustar ヘッダブロック ({{man|5|tar|POSIX ustar Archives}}) をシェルスクリプトの機能を使ってストリーミング方式で検査する場合です: |
||
+ | {{Note|{{ic|count}} オプションの引数にある {{ic|B}} サフィックスは GNU coreutils v9.1 の [https://github.com/coreutils/coreutils/commit/97e9778296ead515e77a64942b84f88dcf36a176 新しく導入された] 機能で、 [[dd#VFAT ファイルシステムイメージのボリュームラベルを表示する]] と同じ効果を持っている。 この機能は、{{ic|1=count=256k}}のように、''dd'' がバイトではなく262144個の入力ブロックをコピーすることを示すオプションと混同される可能性があります。}} |
||
+ | {{bc|<nowiki>hexdump-field() { |
||
+ | set -o pipefail |
||
+ | printf '%s[%d]:\n' $1 $2 |
||
+ | dd count=${2}B status=none | hexdump -e $2'/1 "%3.2x"' -e '" | " '$2'/1 "%_p" "\n"' |
||
+ | } |
||
+ | |||
+ | inspect-tar-header-block() { |
||
+ | local -a hdrstack=( |
||
+ | name 100 |
||
+ | mode 8 |
||
+ | uid 8 |
||
+ | gid 8 |
||
+ | size 12 |
||
+ | mtime 12 |
||
+ | checksum 8 |
||
+ | typeflag 1 |
||
+ | linkname 100 |
||
+ | magic 6 |
||
+ | version 2 |
||
+ | uname 32 |
||
+ | gname 32 |
||
+ | devmajor 8 |
||
+ | devminor 8 |
||
+ | prefix 155 |
||
+ | pad 12 |
||
+ | ) |
||
+ | set - ${hdrstack[@]} |
||
+ | while test $# -gt 0; do |
||
+ | hexdump-field $1 $2 || return |
||
+ | shift 2 |
||
+ | done |
||
+ | }</nowiki>}} |
||
+ | $ bsdtar -cf - /dev/tty /dev/null 2>&- | dd count=1 skip=1 status=none | inspect-tar-header-block |
||
+ | {{tip|''指定された長さ内で入力から出力にデータをストリーミングするには'' という代替案は、{{man|2|splice}} システムコールをサポートする {{man|1|pv|S,}} です。 |
||
+ | {{note|もう 1 つの代替候補は {{man|1|head|c}} ですが、[[coreutils#Alternatives|GNU coreutils 以外の実装]] と glibc [https://unix.stackexchange.com/a/12538#12538 は消費する可能性があります]要求されたデータよりも多くのデータ] が発生し、ストリーミングシェルスクリプトでデータの不整合の問題が発生します。}}}} |
||
+ | {{Tip|上記の機能グリッドに加えて、入力ファイルがストリーミング前に特定のオフセットによって {{man|2|lseek}} され、''dd'' の出力端がプログラムに接続されたパイプである場合は、{{man|2|splice}} の場合、代わりに次の使用を検討できます。 |
||
+ | * シーク機能が組み込まれたシェル (''すでに述べたように [[#前のサブセクションでの代替として、バイナリファイルにブロックごとにインプレースでパッチを適用する'']]) |
||
+ | * または、Bourne のようなシェル (例:[[bash]])、シェルで開かれたファイル記述子に対する 1 回限りの {{man|2|lseek}} 用の {{man|1|xxd|s}} の助けを借りて、 |
||
+ | 次の [[bash]] の例のように {{man|1|pv|S,}} (''前述'') を実行します (ファイル記述子が {{ic|ls -l /proc によってシェルに割り当てられていないと仮定します) 最初は bash の /self/fd}} {{hc|$ bash|<nowiki>$ exec 9<dummy-but-rather-large.img |
||
+ | $ xxd -g 0 -l 0 -s $((0x47ffff)) <&9 |
||
+ | $ pv -qSs 104857601200 <&9 |</nowiki> ''program-that-process-load-of-data-but-does-not-limit-read-length-as-desired-nor-support-offset-read'' |
||
+ | $ exec 9<&-}}{{note|POSIX および一部の非 GNU 実装とは互換性がありませんが、上記の例の {{man|1|xxd|s}} の使用を、{{ic|1=count=0}} と組み合わせた ''dd'' に置き換えることは可能です。および {{ic|skip}} オプション [https://github.com/coreutils/coreutils/blob/4fd708810ce0e0d967c4c14e1ff2ff7b43440b58/tests/dd/skip-seek-past-file.sh#L74 coreutils テストスイートの例]}}}} |
||
+ | |||
+ | === ブータブルなディスクイメージをブロックデバイスに書き込み、任意で進捗情報を表示する === |
||
+ | |||
+ | その場合に最も適合性が低い可能性がある ''dd'' を含むコモディティ ユーティリティの例については、[[USB インストールメディア#基本的なコマンドラインユーティリティを使う]] を参照してください。 |
||
+ | {{tip|''ファイルの内容をブロックデバイスに書き込む (進行状況インジケーター付き)'' という代替案として、{{man|1|dd_rescue|W}} が推奨されます。デバイス上の古いバージョンのイメージを新しいバージョンで上書きする場合、不要な書き込みを回避できます。}} |
||
+ | |||
+ | == トラブルシューティング == |
||
+ | |||
+ | === 部分読み取り: コピーされたデータは要求されたデータよりも小さい === |
||
+ | |||
+ | [https://www.gnu.org/software/coreutils/manual/html_node/dd] のように、現時点で完全な入力ブロックが利用できない場合、''dd'' で作成されたファイルは要求されたサイズよりも小さくなる可能性があります。[https://www.gnu.org/software/coreutils/manual/html_node/dd-invocation.html#dd-invocation per ドキュメント]: |
||
+ | |||
+ | :''さらに、データ変換する {{ic|conv}} 被演算子 ''(つまり、この Wiki 記事のようなオプション)'' が指定されていない場合、入力は読み取られるとすぐに出力にコピーされます。ブロックサイズより小さいです。'' |
||
+ | |||
+ | Linuxでは、{{man|2|read}} システムコールは {{man|7|pipe}} から読むとき、または {{ic|/dev/urandom}} や {{ic|/dev/random}} などのデバイスファイルを読むときに早く戻ることがあります (つまり、''部分読み'') (例えば、[https://unix.stackexchange.com/a/178957#178957 基礎となるカーネルデバイスドライバーのハードコーディングされた制限] またはエントロピーが不十分です) ここで {{ic|''n''}} は出力にコピーする入力ブロックの最大数 (''潜在的な部分'') を制限します。 |
||
+ | |||
+ | 可能性はありますが、保証はできません。''dd'' がそのような種類の問題について警告する可能性があります。 |
||
dd: warning: partial read (''X'' bytes); suggest iflag=fullblock |
dd: warning: partial read (''X'' bytes); suggest iflag=fullblock |
||
+ | 解決策は、警告にあるように、入力ファイルオプションに加えて {{ic|1=iflag=fullblock}} オプションを ''dd'' コマンドに追加することです。たとえば、合計長が 40 MB のランダム データで満たされた新しいファイルを作成するには、次のようにします。 |
||
− | The solution is to do as the warning says and add {{ic|1=iflag=fullblock}} to the ''dd'' command. For example: |
||
+ | |||
+ | $ dd if=/dev/urandom of=new-file-filled-by-urandom.bin bs=40M count=1 iflag=fullblock |
||
+ | |||
+ | {{Note|パイプや特殊なデバイスのファイルから読み込む際に、{{ic|1=count=''n''}} オプションを指定して、ファイルの一部を固定長でコピーすることが推奨されます、また、[[dd#ブートローダーの削除|デバイスの一部]] や [[ディスクの完全消去/ヒントとテクニック#単体ファイルの消去|ファイル]] を [[ディスクの完全消去|完全消去]] する場合は、{{ic|1=iflag=fullblock}} オプションを追加して''dd'' コマンドで行うことを常に強くお勧めします。}} |
||
+ | |||
+ | パイプから読み込む場合、{{ic|1=iflag=fullblock}} の [https://unix.stackexchange.com/questions/556016/cat-dd-pipe-causes-partial-reads-without-iflag-fullblock-why-truncated-to-128 代替案] として、{{ic|bs}} を [https://elixir.bootlin.com/linux/latest/A/ident/PIPE_BUF {{ic|linux/limits.h}}] で定義されている {{ic|PIPE_BUF}} 定数に制限して {{man|7|pipe}} の I/O を原子化します。例えば、全長5メガバイトのランダムな英数字で埋め尽くされたテキストファイルを用意する場合、以下のようになります: |
||
+ | |||
+ | $ LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | dd of=passtext-5m.txt bs='''4k''' count=1280 |
||
+ | |||
+ | 出力ファイルはパイプではないため、(''入力'') パイプと (''出力'') ディスク上のファイル。たとえば、出力ファイルのより効率的なブロック サイズを設定するには、次のようにします。 |
||
+ | |||
+ | $ LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | dd of=passtext-5m.txt ibs=4k obs=''64k'' count=1280 |
||
+ | |||
+ | {{tip|状況によっては、出力ブロックサイズを入力ブロックサイズと同じ値に保つだけで、{{ic|PIPE_BUF}} 定数で定義された値がすでに最適である場合があります。}} |
||
+ | === 総転送バイト数の読み出しが間違っている === |
||
− | $ dd if=/dev/random of=bigsecret.img bs=1K count=1 iflag=fullblock |
||
− | $ dd if=/dev/urandom of=bigsecret.img bs=40M count=1 iflag=fullblock |
||
+ | 以下の概念実証のように、出力への書き込み時にエラーが発生した場合 (例えば、SIGPIPE、欠陥のある媒体、または誤ってターゲットネットワークブロックデバイスを切断したことによる ''部分書き込み'')、読み出された総転送バイト数は実際よりも大きくなる可能性があります:第2の ''dd'' は明らかに512200バイト以上を読みませんが、第1の ''dd'' インスタンスはまだ不正確なバイト数512400バイトを報告します: |
||
− | {{Note|It is strongly recommended to always add the {{ic|1=iflag=fullblock}} option to the ''dd'' command when the input file is {{ic|/dev/random}} or {{ic|/dev/urandom}}.}} |
||
+ | $ yes 'x' | dd bs=4096 count=512400B | dd ibs=1 count=512200 status=none >/dev/null |
||
− | An alternative for {{ic|/dev/urandom}} is to specify a block size smaller than 32 MiB, but a larger copy count. For example: |
||
+ | 125+1 records in |
||
+ | 125+1 records out |
||
+ | 512400 bytes (512 kB, 500 KiB) copied, 10.7137 s, 47.8 kB/s |
||
+ | 上記の PoC のように中断された転送を再開する場合、"+" 記号の前の数字で示されるように、既にコピーされた全出力ブロックの数の読み出しのみに依存することをお勧めします。 |
||
− | $ dd if=/dev/urandom of=bigsecret.img bs=1M count=40 |
||
+ | {{Note|{{ic|1=iflag=fullblock}} オプションを追加しても、部分I/Oブロック数が1より大きい場合は、部分 I/O が2回以上発生したことになります。 この場合、確実に転送を再開するために、次のことをお勧めします: |
||
+ | * 潜在的な欠陥媒体の部分読み出しに柔軟に対処するために、代わりに [[ddrescue]] を使用して転送を再実行する。 |
||
+ | * ネットワーク接続が悪い状態で nbd に書き込む場合、{{man|1|dd_rescue}} を使って直接 I/O で転送を再実行する。 |
||
+ | * 欠陥のある媒体への書き込みを避けることができます。}} |
||
+ | == 参照 == |
||
− | When reading from a pipe, an alternative to {{ic|1=iflag=fullblock}} is to limit {{ic|bs}} to the {{ic|PIPE_BUF}} constant value, defined in {{ic|/usr/include/linux/limits.h}} [https://unix.stackexchange.com/questions/556016/cat-dd-pipe-causes-partial-reads-without-iflag-fullblock-why-truncated-to-128]. For example: |
||
+ | * {{man|1p|dd}}: の [[man ページ|manpage]] dd コアユーティリティ POSIX 仕様 |
||
− | $ cat input.img | dd of=output.img bs=4k count=100 |
2024年2月20日 (火) 19:35時点における最新版
dd はファイルの変換とコピーを主な目的とする コアユーティリティ です。
cp と同様にデフォルトでは dd はファイルのビットごとのコピーを作成しますが、低レベルの I/O フロー制御機能を備えています。
詳細は、dd(1) またはフルドキュメントを参照してください。
インストール
dd は GNU coreutils の一部です。このパッケージ内の他のユーティリティについては、Core utilities を参照してください。
ディスクの複製と復元
dd コマンドはシンプルでありながら多機能で強力なツールです。ファイルシステムの種類や OS に関係なく、コピー元からコピー先へブロック単位でコピーすることができます。ライブ CD のようなライブ環境から dd を使用するのが便利です。
パーティションの複製
物理ディスク /dev/sda
のパーティション 1 から、物理ディスク /dev/sdb
のパーティション 1 へ:
# dd if=/dev/sda1 of=/dev/sdb1 bs=64K conv=noerror,sync status=progress
ハードディスク全体の複製
物理ディスク /dev/sda
から物理ディスク /dev/sdb
へ:
# dd if=/dev/sda of=/dev/sdb bs=64K conv=noerror,sync status=progress
このコマンドは、パーティションテーブル、ブートローダー、すべてのパーティション、UUID、データを含むドライブ全体を複製します。
bs=
はブロックサイズを設定します。デフォルトは512バイトで、これは1980年代前半以降のハードドライブの「古典」的なブロックサイズですが、最も便利なものではありません。64KBや128KBなど、より大きな値を使用してください。また、「ブロックサイズ」だけでなく、読み取りエラーの伝搬にも影響を与えるため、下記の警告をお読みください。詳細は、[1] と [2] を参照して、最適な bs 値を見つけてください。noerror
はすべての読み取りエラーを無視して操作を続けるように dd に指示します。dd のデフォルトの動作は、いかなるエラーでも停止します。sync
は読み込みエラーがあった場合、入力ブロックをゼロで埋め、データのオフセットは同期されたままになります (読み込みエラーが疑われる場合、sync を用いた際の読み込みエラーの挙動に関する下記の詳細な説明を見てください)。status=progress
は、操作がいつ完了するかを推測するために使用できる転送統計を表示します。
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 になります。ただし、コピー元のディスクで発生した読み取りエラーは、コピー先のディスクではブロックエラーとして発生することに注意してください。つまり、512バイトのリードエラーは、出力先の 64 KiB ブロック全体をめちゃくちゃにします。
パーティションテーブルのバックアップ
fdisk#パーティションテーブルのバックアップとリストア または gdisk#パーティションテーブルのバックアップとリストア を参照。
ディスクイメージの作成
ライブ環境のメディアから起動し、ソースのハードドライブのパーティションがマウントされていないことを確認してください。
次に、外部のハードドライブをマウントし、ドライブをバックアップしてください:
# dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c > /path/to/backup.img.gz
必要であれば (出力ファイルが FAT32 ファイルシステム上に保存される場合など)、ディスクイメージを複数に分けてください (split(1) も見てください):
# dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c | split -a3 -b2G - /path/to/backup.img.gz
ローカルに十分なディスクスペースがない場合、イメージを ssh を通して送ることもできます:
# dd if=/dev/sda conv=sync,noerror bs=64K | gzip -c | ssh user@local dd of=backup.img.gz
最後に、イメージに保存されているパーティションテーブルを解釈するために必要な、ドライブのジオメトリ情報に関する追加情報を保存します。最も重要なのはシリンダーサイズです。
# fdisk -l /dev/sda > /path/to/list_fdisk.info
システムの復元
システムを復元するには:
# gunzip -c /path/to/backup.img.gz | dd of=/dev/sda
イメージが分割されている場合は、代わりに以下を使用してください:
# cat /path/to/backup.img.gz* | gunzip -c | dd of=/dev/sda
MBR のバックアップと復元
ディスクに変更を加える前に、ドライブのパーティションテーブルとパーティションスキームをバックアップしておくと良いでしょう。また、同じパーティションレイアウトを複数のドライブにコピーするためにバックアップを使うこともできます。
MBR はディスクの先頭 512 バイトに格納されています。MBR は4つの部分から成ります:
- 始めの 440 バイトにはブートストラップコード (ブートローダ) が含まれています。
- 次の 6 バイトにはディスクのシグネチャが含まれています。
- 次の 64 バイトにはパーティションテーブルが含まれています (各16バイトの4つのエントリ、各プライマリパーティションに1つのエントリ)。
- 最後の 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 の先頭 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
ディスク関連や他の使用場面
既にお気づきの方もいらっしゃるかもしれませんが、dd(1) コアユーティリティは他のユーティリティと比較して かなり異なる コマンドラインのシンタックスを持っています。さらに、他のコモディティユーティリティにはないユニークな機能 をサポートしていますが、特定のシナリオに適用すると、あまり理想的でない かpotential error-prone デフォルト動作 (時には、できないこと) がいくつも存在します。そのため、ユーザーは dd コアユーティリティの代わりに、ある面ではより優れた代替品を使いたいと思うかもしれません。
そうは言っても、dd は core utility であり、Arch や他の多くのシステムにデフォルトでインストールされているため、代替ユーティリティやより専門化されたユーティリティよりも好ましいことに注意する必要があります。システムに新しいパッケージをインストールするのは不便です。
上記で説明した 2 つの側面をカバーするために、このセクションでは、他の汎用ユーティリティではほとんど見られない dd(1) コア ユーティリティの機能を、Pacman/比較表 の記事に似た形式で要約することに専念します。ただし、サンプルの量は、dd のこれらの機能を調べるのに十分な量 (ヒント: の ie または To 節で示されています) にできる限り少なく、単純に削減されています。サブセクションの下のボックス)、実践または疑似コードのいずれかにおいてです.
バイナリファイルにブロック単位のパッチをインプレースに適用する
自動シェルスクリプトで機能が限定されたバイナリファイルパッチャーとして dd を使用することは珍しいことではありません。これは、書き込み前に指定されたオフセットによって出力ファイルを seek
することができ、ブロックすることができるためです。 conv=notrunc
オプションを追加して、出力ファイルにブロック単位 (または bs=1
の場合はバイト y バイト) でインプレースパッチを適用します。
たとえば、cpio(5) § Portable ASCII Format アーカイブ内の最初のメンバーのタイムスタンプ部分を変更するには、ファイルの 49 番目のバイトから始まります (または、次の場合は 0x30
のオフセットで始まります)。16 進表記を好む場合):
$ touch a-randomly-chosen-file $ bsdtar -cf example-modify-ts.cpio --format odc -- a-randomly-chosen-file
$ printf '%011o' "$(date -d "2019-12-21 00:00:00" +%s)" | dd conv=notrunc of=example-modify-ts.cpio seek=48 oflag=seek_bytes
VFAT ファイルシステムイメージのボリュームラベルを表示する
ファイルシステム VFAT のボリュームラベル イメージファイルを読み取るには、ASCII スペースが埋め込まれた全長 11 バイトで、オフセットは 0x047
です。:
$ truncate -s 33M empty-hole.img $ fatlabel empty-hole.img LabelMe
$ dd iflag=skip_bytes,count_bytes count=11 skip=$((0x047)) if=empty-hole.img | sed -e 's% *$%%'
パイプで繋がれたコマンド間で sponge する
次の例では、出力側のブロックが予想より長くなった場合に、入力側で不必要に長く続く TCP 接続を避けるために、2 つのコマンドの間に dd を挿入し、出力ブロックサイズは入力よりも確実に大きく、それでも使用可能なメモリよりはかなり小さいものにすることができます。
$ curl -qgsfL http://example.org/mirrors/ftp.archlinux.org/mirrored.md5deep | dd ibs=128k obs=200M | poor-mirroring-script-that-perform-mirroring-on-input-paths-line-by-line-wo-buffer-entire-list-first
サイズの制限付きでデータを転送する
データストリーミングのシェルスクリプトで dd を使用すると、パイプコマンドで消費されるデータの合計長を制限することができるのは一般的です。例えば、ustar ヘッダブロック (tar(5) § POSIX ustar Archives) をシェルスクリプトの機能を使ってストリーミング方式で検査する場合です:
hexdump-field() { set -o pipefail printf '%s[%d]:\n' $1 $2 dd count=${2}B status=none | hexdump -e $2'/1 "%3.2x"' -e '" | " '$2'/1 "%_p" "\n"' } inspect-tar-header-block() { local -a hdrstack=( name 100 mode 8 uid 8 gid 8 size 12 mtime 12 checksum 8 typeflag 1 linkname 100 magic 6 version 2 uname 32 gname 32 devmajor 8 devminor 8 prefix 155 pad 12 ) set - ${hdrstack[@]} while test $# -gt 0; do hexdump-field $1 $2 || return shift 2 done }
$ bsdtar -cf - /dev/tty /dev/null 2>&- | dd count=1 skip=1 status=none | inspect-tar-header-block
ブータブルなディスクイメージをブロックデバイスに書き込み、任意で進捗情報を表示する
その場合に最も適合性が低い可能性がある dd を含むコモディティ ユーティリティの例については、USB インストールメディア#基本的なコマンドラインユーティリティを使う を参照してください。
トラブルシューティング
部分読み取り: コピーされたデータは要求されたデータよりも小さい
[3] のように、現時点で完全な入力ブロックが利用できない場合、dd で作成されたファイルは要求されたサイズよりも小さくなる可能性があります。per ドキュメント:
- さらに、データ変換する
conv
被演算子 (つまり、この Wiki 記事のようなオプション) が指定されていない場合、入力は読み取られるとすぐに出力にコピーされます。ブロックサイズより小さいです。
Linuxでは、read(2) システムコールは pipe(7) から読むとき、または /dev/urandom
や /dev/random
などのデバイスファイルを読むときに早く戻ることがあります (つまり、部分読み) (例えば、基礎となるカーネルデバイスドライバーのハードコーディングされた制限 またはエントロピーが不十分です) ここで n
は出力にコピーする入力ブロックの最大数 (潜在的な部分) を制限します。
可能性はありますが、保証はできません。dd がそのような種類の問題について警告する可能性があります。
dd: warning: partial read (X bytes); suggest iflag=fullblock
解決策は、警告にあるように、入力ファイルオプションに加えて iflag=fullblock
オプションを dd コマンドに追加することです。たとえば、合計長が 40 MB のランダム データで満たされた新しいファイルを作成するには、次のようにします。
$ dd if=/dev/urandom of=new-file-filled-by-urandom.bin bs=40M count=1 iflag=fullblock
パイプから読み込む場合、iflag=fullblock
の 代替案 として、bs
を linux/limits.h
で定義されている PIPE_BUF
定数に制限して pipe(7) の I/O を原子化します。例えば、全長5メガバイトのランダムな英数字で埋め尽くされたテキストファイルを用意する場合、以下のようになります:
$ LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | dd of=passtext-5m.txt bs=4k count=1280
出力ファイルはパイプではないため、(入力) パイプと (出力) ディスク上のファイル。たとえば、出力ファイルのより効率的なブロック サイズを設定するには、次のようにします。
$ LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | dd of=passtext-5m.txt ibs=4k obs=64k count=1280
総転送バイト数の読み出しが間違っている
以下の概念実証のように、出力への書き込み時にエラーが発生した場合 (例えば、SIGPIPE、欠陥のある媒体、または誤ってターゲットネットワークブロックデバイスを切断したことによる 部分書き込み)、読み出された総転送バイト数は実際よりも大きくなる可能性があります:第2の dd は明らかに512200バイト以上を読みませんが、第1の dd インスタンスはまだ不正確なバイト数512400バイトを報告します:
$ yes 'x' | dd bs=4096 count=512400B | dd ibs=1 count=512200 status=none >/dev/null 125+1 records in 125+1 records out 512400 bytes (512 kB, 500 KiB) copied, 10.7137 s, 47.8 kB/s
上記の PoC のように中断された転送を再開する場合、"+" 記号の前の数字で示されるように、既にコピーされた全出力ブロックの数の読み出しのみに依存することをお勧めします。