🎃

WSL2のUbuntuを別マシンに移行しようとして盛大にハマった話 ― 失敗から生まれた手順書

に公開

はじめに

「ext4.vhdx をコピーすれば環境は移るだろう」

……と軽い気持ちで始めた WSL2 の Ubuntu 移行作業が、想定外のエラーと仕様の落とし穴に次々と引っかかり、かなりの時間を溶かしました。この記事は、その 試行錯誤の全記録 です。

この記事を読むと分かること:

  • WSL2 ディストリビューションの移行で陥りやすい 失敗パターン とその見分け方
  • wsl --export / wsl --import の正しい使い方と落とし穴
  • Optimize-VHD が動かない場合の原因切り分けと対処
  • VHDX を安全に小さくするためのクリーンアップ手順

1. 発端 ―「コピーすれば移るだろう」

やりたかったこと

他のマシンで同じ開発環境を使いたくて、WSL2 の Ubuntu 22.04 を別マシンに移行しようとしました。作業前の仮説はめちゃくちゃシンプルでした。

ext4.vhdx(WSL の仮想ディスク)をコピーすれば、そのまま環境が移るでしょ?

実際にやったこと(時系列)

最初はシンプルに進めるつもりでした。ざっくりこんな流れです。

① まず wsl --unregister で既存の登録を解除

一旦 unregister して登録を消しました。

wsl --unregister Ubuntu-22.04

② D ドライブにディストリを登録

VHDX ファイルを D ドライブにコピーして、--import-in-place で直接登録しました。tar を経由せず、VHDX をそのまま使えるコマンドです。

wsl --import-in-place Ubuntu-22.04 D:\WSL\Ubuntu-22.04\ext4.vhdx

ここまでは順調。

③ 起動したら root だった

インポート後にいざ起動してみると root@... で立ち上がりました。
元のユーザーで入れない。ということで ubuntu2204.exe config --default-user でデフォルトユーザーを設定し直して対応。

④ そして地獄が始まった

ユーザー設定は解決したのに、今度は起動が安定しなくなりました。起動できるときもあれば、以下のエラーが出て起動できないときもある。

ディスク '\\?\D:\WSL\Ubuntu-22.04\ext4.vhdx' を WSL2 にアタッチできませんでした: アクセスが拒否されました。
エラー コード: Wsl/Service/CreateInstance/MountDisk/HCS/E_ACCESSDENIED

「さっきまで動いてたのに……?」の繰り返し。
再現条件がよく分からないのが困りました。

ハマったこと一覧

最終的にぶつかった問題をまとめるとこうなります。

# 起きたこと ざっくり原因
1 VHDX コピーしても動かない WSL のレジストリ登録が別途必要だった
2 wsl --import がエラー インポート先フォルダに残骸が残ってた
3 Optimize-VHD が見つからない Hyper-V 管理ツールが無効だった
4 インポート後に root で起動する デフォルトユーザー情報が引き継がれてない
5 E_ACCESSDENIED で起動が不安定 VHDX のロック / 権限 / WSL サービスの状態

結論から言うと、これらは全部バラバラの問題じゃなくて、様々な前提条件が絡み合った結果でした。

2. まずやるべき診断 ― 現状把握のためのコマンド集

問題を切り分けるために、まず現状を正確に把握する必要があります。私が実際に使った診断コマンドを、Windows 側Ubuntu 側に分けて紹介します。

Windows 側(PowerShell)

登録済みディストリビューション一覧
wsl --list --verbose
WSLを完全停止(VHDXのロック解除)
wsl --shutdown

3. よくある失敗パターンとその見分け方

今回の作業で遭遇した(または調査中に判明した)失敗パターンを、症状→見分け方→対処法 の形式でまとめます。

パターン A:インポート先フォルダが空でない

💥 症状
wsl --import 実行時に「インストール場所は既に使用されています」とエラーが出る。

🔍 見分け方

フォルダが存在するかどうか確認
dir "D:\WSL\Ubuntu-22.04"

✅ 対処法

既存フォルダを削除して空の状態から再作成
Remove-Item "D:\WSL\Ubuntu-22.04" -Recurse -Force
New-Item -ItemType Directory "D:\WSL\Ubuntu-22.04"
改めてインポート
wsl --import Ubuntu-22.04 "D:\WSL\Ubuntu-22.04" "E:\TEMP\Ubuntu-22.04.tar"

パターン B:誤ったインポート引数でディストリビューション名が変わる

💥 症状
意図しない名前のディストリビューションがある。

🔍 見分け方

意図しない名前のディストリビューションが存在するかどうか確認
wsl --list --verbose

✅ 対処法

誤登録を削除
wsl --unregister ext4.vhdx
正しい引数で再インポート
wsl --import Ubuntu-22.04 "D:\WSL\Ubuntu-22.04" "E:\Ubuntu-22.04.tar"

パターン C:デフォルトユーザーが root のまま

💥 症状
起動すると root@... でログインされる。/home にはユーザーディレクトリが存在しているのに。

🔍 見分け方

ユーザーディレクトリは存在するかどうか確認
ls /home

✅ 対処法

Windows 側でデフォルトユーザーを再設定

ubuntu2204.exe config --default-user <ユーザー名>

パターン D:Optimize-VHD が使えない

💥 症状

  • Optimize-VHD コマンドが見つからない

🔍 見分け方

エラーがでないかどうか確認
Get-Command Optimize-VHD

✅ 対処法

  1. Hyper-V 管理ツールを有効化する(GUI の場合)

    • 「Windows の機能の有効化または無効化」を開く
    • Hyper-V 管理ツール」にチェック → 再起動
  2. WSL 停止後に実行

WSL 停止
wsl --shutdown
最適化
Optimize-VHD -Path "D:\WSL\Ubuntu-22.04\ext4.vhdx" -Mode Full

4. VHDX 圧縮前にやるべきクリーンアップ

Optimize-VHDwsl --export の前に、再生成可能な不要データ を削除しておくと、ファイルサイズを大幅に削減できます。

優先度:高(削除で効果大)

対象 コマンド 理由
apt キャッシュ sudo apt clean && sudo apt autoremove -y .deb パッケージが大量に溜まる
pip キャッシュ pip cache purge Python パッケージのキャッシュが肥大化
Docker のイメージ/コンテナ docker system prune -a -f Docker は VHDX を 急速に 肥大化させる

優先度:中(効果あり)

対象 コマンド
/tmp の一時ファイル sudo rm -rf /tmp/*
journal ログ sudo journalctl --vacuum-size=50M
npm / yarn キャッシュ npm cache clean --force
古いログファイル sudo rm -f /var/log/*.gz /var/log/*.[0-9]

⚠️ 絶対に消してはいけないもの

5. 実際に使った自動化スクリプト

毎回手動で同じコマンドを打つのは非効率なので、スクリプト化しました。実際に私の環境で使っているものをそのまま掲載します。

Ubuntu 内クリーンアップスクリプト

safe-clean.sh(クリックで展開)
safe-clean.sh
#!/usr/bin/env bash
set -e

echo "=== APT キャッシュ削除 ==="
sudo apt clean
sudo apt autoremove -y

echo "=== pip キャッシュ削除 ==="
if command -v pip >/dev/null 2>&1; then
    pip cache purge || true
fi

echo "=== npm キャッシュ削除 ==="
if command -v npm >/dev/null 2>&1; then
    npm cache clean --force || true
fi

echo "=== /tmp の削除 ==="
sudo rm -rf /tmp/*

echo "=== journal の圧縮 ==="
sudo journalctl --vacuum-size=50M

echo "=== Docker のクリーンアップ(インストール済みの場合のみ) ==="
if command -v docker >/dev/null 2>&1; then
    docker system prune -a -f || true
fi

echo "=== 不要ログ削除 ==="
sudo rm -f /var/log/*.gz
sudo rm -f /var/log/*.[0-9]

echo "=== 完了しました ==="

使い方

スクリプト作成
nano safe-clean.sh
スクリプトに実行権限付与
chmod +x safe-clean.sh
実行方法
./safe-clean.sh

実行後、Windows 側で wsl --shutdownOptimize-VHD を実行します。

6. おわりに ― 失敗を記録する価値

「VHDX をコピーすれば移るだろう」という直感は自然なものでした。
今回の一連の失敗でかなりの時間を消費しましたが、得たものは大きかったです。

  • WSL が「単なるファイル」ではなく Windows のコンポーネント群と連携して動いている ことの理解
  • Hyper-V 管理ツールの依存関係と、Windows のエディションによる制約
  • VHDX の最適化が移行サイズに与える影響
  • そして何より、「壊れない運用フロー」 を手に入れたこと

Discussion