ディスクがいっぱいになるまで、「tar」を「dd」にパイプするのが止まらないのはなぜですか?


18

単一のディスクイメージのtarアーカイブがあります。このtarファイル内の画像のサイズは約4GBです。Iパイプの出力tar xfddSDカードにディスクイメージを書き込みます。ディスクダンプは、カードがいっぱいになるまで停止しません。これが私のシェルセッションです。

$ ls -l disk.img.tgz
-rw-r--r-- 1 confus confus 192M Okt  5 00:53

$ tar -tvf disk.img.tgz
-rw-r--r-- root/root 4294968320 2018-10-05 00:52 disk.img

$ lsblk -lb /dev/sdc
NAME MAJ:MIN RM        SIZE RO TYPE MOUNTPOINT
sdc    8:32   1 16022241280  0 disk

$ tar zxf disk.img.tgz -O | sudo dd status=progress conv=sync bs=1M of=/dev/sdc
[sudo] password for user: 
15992881152 bytes (16 GB, 15 GiB) copied, 212 s, 75,4 MB/s 
dd: error writing '/dev/sdc': No space left on device
0+15281 records in
15280+0 records out
16022241280 bytes (16 GB, 15 GiB) copied, 217,67 s, 73,6 MB/s

どうして?ヒットにより4GBの画像が16GBのカートに書き込まれ、スペースがなくなることはありません。


これを実行ddして別のファイルに書き込むためのディスク容量はありますか? tar zxf disk.img.tgz -O | dd status=progress conv=sync bs=1M of=/path/to/some/file/on/disk?もしそうなら、それはあなたに元のファイルの正確なコピーを取得しますか?
アンディダルトン

2
どうしてconv=syncconv=fsyncおそらく使用するつもりでしたか?
ラルフロンキスト

それがファイルの本当のサイズだと確信していますか?gzipにはファイルサイズを保存するための32ビットしかないので、4GBを超えるファイルのサイズが間違っています。tarに同様の制限があるかどうかはわかりません。
デビッドコンラッド

回答:


50

それはあなたが間違っているからです。

あなたは使用してbs=1Mいますが、stdin、パイプからの読み取りはより小さな読み取りになります。実際、ddによると、1回の完全な読み取りは行われませんでした。

そして、あなたはconv=syncゼロで不完全な読み取りを補完するものを持っています。

0+15281 records in
15280+0 records out

dd0の完全な読み取りと15281の不完全な読み取りを受信し、15280の完全なブロックを書き込みました(conv = sync zero fill)。したがって、スペースがなくなるまで、出力は入力よりもはるかに大きくなります。

   sync   pad  every  input  block  with  NULs to ibs-size; when used with
          block or unblock, pad with spaces rather than NULs

これを解決するには、を削除conv=syncして追加しiflag=fullblockます。


説明のために、yesデフォルトで無限の「y \ ny \ ny \ n」を吐き出すを検討してください。

$ yes
y
y
y
^C
$ yes | hexdump -C
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*

ではdd bs=1M conv=sync、それは次のようになります。

$ yes | dd bs=1M conv=sync | hexdump -C
00000000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
0001e000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00100000  79 0a 79 0a 79 0a 79 0a  79 0a 79 0a 79 0a 79 0a  |y.y.y.y.y.y.y.y.|
*
00112000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*

そのため、「y \ ny \ ny \ n」(0x00000-0x1e000、122880バイト)の不完全なブロックを取得し、残りの1Mをゼロ(0x01e000-0x100000、925696バイト)として書き込みます。ほとんどの場合、これが起こるのは望ましくありません。各読み取りがどの程度不完全になるかを実際に制御することはできないため、結果はとにかくランダムです。このように、2番目の読み取りは122880バイトではなく73728バイトになりました。

dd conv=syncまれに有用であり、読み取りエラーが発生したときにゼロを書き込むなど、それが歓迎される場合でも、事態は恐ろしく悪くなります。


この場合、(Linuxを想定して)ddコマンドを実行するとstrace、パイプからの各短い読み取りの後に完全な1MBの書き込みが続くことが示されます。
アンドリューヘンレ

2
@AndrewHenleはこのためにstraceも必要としません。出力を見るだけで十分です。イラストを追加
frostschutz

これddは、コマンドが根本的に壊れて使用できない理由も示しています。個々readのsおよびwritesで動作するように指定されていますが、これらの操作は、常に短い読み取りまたは書き込みを生成できるように指定されており、エラーではありません。結果として、の動作はdd不特定の動作に依存します。
R ..

非常に教育的な答えをありがとう。他の誰かが示唆したように、私はお尻であり、多くのオプションを混同してddいましたが、あなたから何かを学ぶことにつながりました。私がまだ完全に確信していないのは、いつdd終了するかということです。あると思いますが、実際には1部の実際のデータと9部のゼロを書き込んでいたので、約40Gを書き込んだ後に停止したでしょう。あれは正しいですか?
con-f-use

@R ..、この機能は、読み取りと書き込みのブロックサイズを考慮するデバイスドライバーで非常に役立ちます。私はそれを気にしたいくつかのテープドライブを使用したことを覚えています。この場合、それは明らかに必要ではありませんが、ディスクに直接リダイレクトすることができます(ただし、進行状況レポートは取得しません)
-ilkkachu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.