dd
を使用してUSBドライブを.img
ファイルにコピーしました。
dd if=/dev/sdc of=myimage.img
イメージ内のパーティションのサイズを縮小したい。私はいくつかの方法を試しましたが、パーティションがまだUSBのフルサイズであるループバックマウントイメージになります。
ループバックマウントされた後、myimage.img
を変更して、パーティションを小さくするにはどうすればよいですか?
そうする前に、パーティションの空の部分にゼロをコピーする必要がありますか?
画像サイズを小さくしたときに空のバイトを削除するようにデフラグする必要がありますか? (私が読んだところによると、Linuxはパーティション全体に広がっているので、イメージの最後にあるすべてのデータがゼロバイトであるとは思いません。すべてゼロを書き込んでも、どこにいても空のバイトを消費するだけです。)
注:ディスク容量を節約しようとはしていないので、圧縮しても役に立ちません。
[〜#〜]背景[〜#〜]
ext4
を使用してLinuxをUSBドライブにインストールしています。複数のデバイスのインストールを複製するつもりです。私はこれを成功させましたが、同じUSBドライブ上に、システムとの読み取り専用パーティションと永続ストレージを可能にする小さなパーティションを作成したいと思います。 USBを壊すのではなく、USBのコピーを変更しようとしています。このような背景に気を取られないように願っています。
要するに、私は次のことをしました:
# Create mount point in current directory
Sudo mkdir mnt
# Loopback mount the image
fdisk -l myimage.img
Sudo mount -o offset=<partion_block_start * block_size> myimage.img mnt
# Copy all zeros to remaining space of the image
cd mnt
Sudo dd if=/dev/zero of=filler conv=fsync bs=1M
rm filler
cd ..
まず、 このスーパーユーザーの回答 で説明されているようにparted
を使用し、 この他のスーパーユーザーの回答 で説明されているようにqemu-img
を使用しようとしました。
Sudo umount mnt
parted myimage.img
# At parted command Prompt
(parted) resizepart 1
# Entered my end <target size>. Note that parted uses zero-based
# indexing. This could be your final image size. In my case, the way the
# Linux installer worked, the partition started at 1M.
(parted) print
# I see that the partition is now sized as I expect
(parted) exit
# Just another sanity check
Sudo parted -m esp3_007.img unit B print
# I see that the partition is now sized as I expect
イメージを再度マウントしようとすると、正常に動作しますが、df
はパーティションを同じサイズで表示します。だから私は試しました
qemu-img resize myimage.img <target_size>
そして今、イメージをマウントしようとすると、「マウント:間違ったfsタイプ、不正なオプション、不正なスーパーブロック...」というエラーメッセージが表示されます。
次に、 このオフサイト投稿 で説明されているようにgparted
を使用してみました。そもそもparted
を実行しない限り、GUIは完全なパーティションを示していました。それでも、GUIではパーティションのサイズを変更できませんでした。
パーティションサイズを強制的に小さくしようとし、myimage.img
の新しいコピーから始めて、 このAskUbuntuの回答 で説明されているfdisk
を試しました。
Sudo fdisk myimage.img
Command (m for help): d
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4, default 1): 1
# defaults on the rest seemed to be correct in my case.
パーティションをマウントしたところ、同じサイズで表示されていました。
まず、offset=
を忘れて、losetup --partscan
を使用し、/dev/loop0p1
を介してパーティションをマウントします。
# losetup --partscan /dev/loop0 myimage.img
# lsblk
# mount /dev/loop0p1 /mnt
パーティション内の空き領域を効率的にクリアするには、SSDの場合と同じように、ループマウントされたファイルシステムでfstrim
を実行します。 (これにより、実際には画像ファイルがまばらになります。)
# fstrim -v /mnt
しかし今のところ、空のスペースを空けるなどのことをする必要はありません。切り捨てられる領域がゼロで埋められているか、古いデータのチャンクで埋められているかは、まったく関係ありません。
代わりに、実際のディスクでext4を使用する場合とまったく同じように実行する必要があります。つまり、各レイヤーを裏返しに縮小する必要があります。画像だからといって手順をスキップすることはできません。
ファイルシステムを含むパーティションを縮小するには、最初にfilesystemにそれ自体を縮小するように指示する必要があります。 ext2/3/4の場合、これはresize2fs
を使用して行われます。これにより、切り落とそうとしている領域に存在する可能性のあるデータが再配置され、ファイルシステムのメタデータの一部として新しい境界が保存されます。 (それが「デフラグ」の意味だと思います。)
ファイルシステムが縮小された後でのみ、それを含むパーティションを縮小することもできます。これは、パーティションの終了アドレスを変更するだけで、partedまたはfdiskを介して実行できます。
補足:あなたはshould GPartedを使用して、ファイルシステムとパーティションのサイズを1つのステップで変更できます。ループデバイスでの作業をサポートしている場合、つまりです。 GPartedのバージョンによって異なる場合があります。 (ただし、CLI partedはファイルシステムを縮小できず、パーティションを切り捨てるだけです。)
最後に、ファイルシステムとパーティションの両方のサイズが変更されたら、それらを含むイメージ全体を切り捨てることができます。これを行うには、最初にループデバイスを切り離し、画像ファイルでtruncate --size=...
を使用します。
(慎重な計算を行わずに安全に行うには、ファイルシステムを必要以上に縮小して「バッファ」スペースを作成します。たとえば、4 GBのイメージが必要な場合は、ファイルシステムを3GBのパーティションに縮小します。 3.5 GBに調整してから、イメージを4 GBに切り捨てます。次に、すべてを逆の順序で拡大して、「バッファー」スペースを埋めます。)