🐧

VirtualBox Ubuntu の仮想ディスク用ファイルのサイズを縮小 - Linux 使いになりたい人向け

2024/01/21に公開

はじめに

この記事は VirtualBox で Ubuntu を使っている人で Linux 使いになりたい人向けの内容で書いてあり、対象者は次の人です。

  • VirtualBox に興味がある
  • VirtualBox の仮想ディスクの管理に興味がある
  • Linux が使えるようになりたい

筆者は Linux 使いで、基本的に Linux 環境で動作確認をしています。ここで紹介しているようなちょっとしたことを少しずつ知ることを毎日続けることで Linux の機能を少しずつ理解することができるようになりました。Linux が使えるようになりたいと思っている人向けに、記事を公開していく予定です。

VirtualBox の仮想ディスク

VirtualBox の仮想ディスクは動的にサイズが変わる設定としてあると、ディスク内に保存するファイルの総サイズに応じて、仮想ディスク用ファイルのサイズが増えていきます。ただし、一度増えてしまったディスク容量は、ファイルを削除しても縮退はしません。

自分は、VirtualBox の仮想マシン内で Docker を使うことが多いのですが、気がつくとディスク使用率が高くなっていて、使っていない Docker イメージが残っていることが多くなっています。そういった場合には Docker イメージ削除をして容量を空けるようにしています。

ここで、定期的に仮想マシンのバックアップを取っているので、このときのファイルサイズは小さくしておきたいのですが、最初に説明したとおり、仮想ディスク内のファイルを削除しても、仮想ディスク自体のファイルサイズは小さくなりません。

ということで、この仮想ディスクのファイルサイズを小さくしたいので調べてみました。単純にパーティション操作をしてファイルサイズを小さくしようとすると、ディスクのデータを壊してしまうかもしれません。拡大時は単純にパーティションを大きくしてから、ファイルシステムへ反映することができますが、縮小時には縮小対象の領域にファイルデータがないことを確認してからでないと問題が起きる可能性があります。

このあたりを調べて整理してくれる機能にデフラグ機能というのがあるのですが、必ずしもパーティションを小さく出来るようにするところまでしてくれるわけでもありませんし、Linux の ext4 ファイルシステムではデフラグが必要ないようで、デフラグツールがありません。

ということで、ext4 でのパーティションを小さくする場合の、うまい対応方法がよくわからないのですが、ファイルシステム上でコピーしてあげれば、データ欠損は発生しないはずなので、それで対応する方針としています。

これはつまり、元の仮想ディスクよりもサイズが小さい別の仮想ディスクを用意して、そちらへ tar コマンドでファイルコピーするということです。

新しい仮想ディスクの用意

最初に、新規に空の仮想ディスクを作成します。サイズはコピー元のデータをコピーするのに十分で余裕のあるサイズにします。

  1. VirtualBox の画面からツールを起動
  2. 作成をクリックして、コピー先のディスクを作成

使用する仮想マシンは CD のイメージから起動するようにし、仮想マシンにはコピー前のディスクと、コピー先のディスクを追加した構成にします。

  1. 仮想マシンへ新しく作成した仮想ディスクを追加
  2. 仮想マシンの CD デバイスに起動用の Ubuntu インストーラー iso ファイルを Live CD/DVD として指定
  3. 仮想マシンのシステムで起動デバイスをCDのみに設定(CD以外のチェックをはずす)

ここで、EFI を有効にしているマシンだと、設定画面での起動で CD を優先にしても、既存の HDD から起動してしまいます。自分は、仮想マシンのファイルから .nvram という拡張子のファイルを削除しています。

  1. 仮想マシンを起動
  2. 起動直後に仮想マシンのコンソール画面をアクティブにして ESC キー連打
  3. UEFI設定画面が表示されたら Boot Manger で CD から起動

CD からの起動が成功すると、Ubuntu インストーラー用の GRUB メニューが表示されます。起動メニューから Try Ubuntu を選択して起動します。

ここで、起動した Ubuntu ではコピー元は /dev/sda、コピー先は /dev/sdb と認識されているとします。この場合、/dev/sda1 が EFI System Partision、/dev/sda2 が Ubuntu の root ファイルシステムとなっています。それぞれを /dev/sdb1、/dev/sdb2 へコピーすれば良いので、そのための作業をします。

gparted の利用

ディスクのパーティション作成やフォーマットには gparted を使うのが楽です。また、dosfstools、mtools といった apt パッケージが必要なのでインストールしてから gparted を起動します。

  1. ターミナルを起動して、sudo apt update && sudo apt -y install dosfstools mtools を実行
  2. ターミナルから sudo gparted を実行
sudo apt update && sudo apt -y install dosfstools mtools
sudo gparted

gparted はディスクを変更するツールなので、対象となるディスクを間違えないように注意します。今回は /dev/sdb は新規に用意したものなのでパーティションがありません。/dev/sda はパーティションがあります。それで区別がつくので、間違えることはないでしょう。

/dev/sdb について、パーティションを /dev/sda と同じ構成で作成します。

  1. /dev/sdb のパーティションテーブルを gpt タイプで作成
  2. /dev/sdb1 のパーティションを作成(/dev/sda1 の情報を参照して設定)
  3. /dev/sdb2 のパーティションを作成(/dev/sda2 の情報を参照して設定)
  4. gparted でディスク操作を確定
  5. /dev/sdb1 のフラグと Name を編集(/dev/sda1 のフラグを参照して boot, esp を設定)
  6. gparted でディスク操作を確定

マウント

gparted でのディスク操作を確定したら、/dev/sda1、/dev/sda2、/dev/sdb1、/dev/sdb2 のマウントをします。これにはディスクツールである gnome-disks を使うのが楽です。

  1. ディスクアプリ起動。ターミナルから起動する場合は sudo /usr/bin/gnome-disks を実行
  2. /dev/sda1 を選択して再生ボタン(マウント)をクリック
  3. /dev/sda1 と同様にして /dev/sda2、/dev/sdb1、/dev/sdb2 についてもマウント

ファイルコピー

ターミナルを起動してファイルコピー。シンボリックリンクを作って作業をすると楽です。

  1. df -k でマウントしているデバイスファイルとパスを確認
  2. シンボリックリンクを作成
  3. 他のパーティションについても同様
  4. EFI システムパーティションは cp コマンドでファイルコピー
  5. ルートディレクトリーは tar コマンドでファイルコピー

シンボリックリンクを作成するにあたっては、df -k で表示されるマウントしているデバイスファイルとパスの情報を参考にします。たとえば /dev/sda1 が /media/ubuntu/F102-71AD にマウントされていたら、次のように ln コマンドを実行します。

ln -s /media/ubuntu/F102-71AD /media/ubuntu/sda1

/dev/sda1 の sda1 を /media/ubuntu/sda1 としてシンボリックリンクのファイル名にしている点に注目してください。ここでは略しますが、他も ln コマンドでシンボリックリンクを用意します。

慣れている人からすると、シンボリックリンクを作ると逆にわかりにくくなるようなら、作らなくても良いです。ここでは、/media/ubuntu に sda1、sda2、sdb1、sdb2 のシンボリックリンクを用意したとします。

用意ができたら、次のようにしてファイルをコピーします。

sudo cp -a /mnt/sda1/* /mnt/sdb1/
cd /mnt/sda2
sudo tar czf - ./* | sudo tar xzf - -C /media/ubuntu/sdb2/

コピーが終わったら、シンボリックファイルの削除と、マウントされていたデバイスについてマウント解除します。

cd /media/ubuntu && sudo rm sda1 sda2 sdb1 sdb2
sudo umount /media/ubuntu/F102-71AD

ここでは /media/ubuntu/F102-71AD 以外は略していますが、他のものもマウント解除しておきます。コマンドではなく、ディスクアプリで、ストップの■をクリックしてマウント解除をしても良いです。

ブートの再設定

使用するディスクが変更となるので、ブートの再設定をします。chroot コマンドで、起動に使うディスクパーティション(ここだと /dev/sdb2)を root ディレクトリーとして扱う環境にします。

chroot 環境の用意

まずは /chroot ディレクトリーを用意して、そこへ /dev/sdb2 をマウントします。

cd /
sudo -s
mkdir /chroot
mount /dev/sdb2 /chroot

このルートディレクトリーを変更した chroot 環境内では、実行時に必要なディレクトリーが足りないので、それらを chroot 環境でも使えるようにします。

for t in dev dev/pts proc sys run; do mount --bind /${t} /chroot/${t}; done

用意ができたら、chroot コマンドで /chroot ディレクトリーをルートディレクトリーとします。

chroot /chroot

chroot 環境で /etc/fstab 編集

実際に使用する起動ディスクの EFI システムパーティションを /boot/efi へマウントします。

mount /dev/sdb1 /boot/efi

/etc/fstab に新しく使うファイルシステムの登録をするために、blkid コマンドで UUID を確認します。

blkid <デバイスファイル名>

/dev/sdb1 と /dev/sdb2 の両方について確認します。UUID を使うので、この値をコピーして、/etc/fstab へ反映します。

$ sudo blkid /dev/sdb1
/dev/sdb1: UUID="2090-E85C" BLOCK_SIZE="512" (略)

/etc/fstab の編集は nano や vi を使います。root 権限が必要なので sudo と組み合わせます。

sudo nano /etc/fstab

chroot 環境で GRUB の再設定

/etc/fstab の編集が終わったら、起動時に使う GRUB の再設定をします。次のコマンドを実行することで、/boot/efi/EFI/ubuntu/shimx64.efiといったファイルができて、OS の起動ができるようになります。

grub-install --efi-directory=/boot/efi
update-grub

設定が終わったら、Ubuntu を終了して、仮想マシンの電源んを一度切ります。

仮想マシンを新ディスクで起動

仮想マシンのシステムの設定で、使用するディスクを新しい仮想ディスク だけにしてから起動するようにします。また、ストレージについて、CD から Live CD/DVD の iso ファイルを取り除きます。それから、仮想マシンを起動します。

なお、仮想ディスクの実際のファイルサイズを確認すると小さくなっているはずです。

Discussion