Ubuntu22.04 on WSL2(Windows10) 環境構築
Introduction
WSL2(Windows10)にUbuntu 22.04をインストールしたときの備忘録です。
インストール方法はいくつかありますが、Ubuntu 20.04をアップグレードする方法で行いました。
手順
Linux カーネル更新プログラム パッケージのインストール
x64マシン用WSL2Linuxカーネル更新プログラムパッケージ( https://aka.ms/wsl2kernel )をインストールします。
すでに最新版がインストール済みの場合には、インストーラを実行しても、インストール済みである旨のメッセージが表示されて何もしません。
仮想マシンプラットフォームを有効化
コントロールパネルで、仮想マシンプラットフォームを有効にします。
コントロールパネル
→ プログラム
→ Windowsの機能の有効化または無効化
→ 仮想マシンプラットフォームを有効にする
WSL 2 を既定のバージョンとして設定する
PowerShellでwslのバージョンを2に設定します。
> wsl --set-default-version 2
Ubuntu 20.04をインストール
現時点(2022/8/23)では、wslコマンドでUbuntu-22.04を直接インストールできませんので、Ubuntu-20.04からアップグレードすることにします。
まず、Ubuntu-20.04をインストールします。PowerShellで、以下のコマンドを実行します。
> wsl --install -d Ubuntu-20.04
途中、Ubuntuコンソールが起動し、Ubuntuの管理ユーザ名、パスワードを聞かれるので入力します。管理ユーザ名は、Windowsのユーザ名と一致する必要はありません。
Installing, this may take a few minutes...
Please create a default UNIX user accout. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: hogehoge
New password:
Retype new password:
いったん、PowerShellに戻り、インストールしたUbuntu-20.04をWSLのデフォルトにセットします。
> wsl --set-default Ubuntu-20.04
DNS解決できない場合の対処
Windows10でインストールした場合、仮想ネットワークアダプターの関係なのか、うまく名前解決ができない場合があります(原因は未調査)。名前解決できない場合には、外部のDNSを設定してしまいます。
先ほどパスワードを入力したUbuntuコンソールに対して、以下の二つのコマンドを入力します。なお、すでに閉じてしまっている場合は、PowerShellからwslと入力すればokです。
$ ping google.com
ping: google.com: Temporary failure in name resolution
$ ping 8.8.8.8 -c 1
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=27.5 ms
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 27.451/27.451/27.451/0.000 ms
ping google.comで上記のようなエラーメッセージが出ていれば、DNSへの接続に失敗しています。また、ping 8.8.8.8が上気のように成功していれば、外部のDNSサーバへの接続が可能です。
ping google.comが成功していれば、この項目の対応は必要ありません。
ping 8.8.8.8が失敗していれば、そもそもネットワークに問題があるようです。
外部のDNSサーバに接続するようにするには、resolv.confファイルを設定します。ただし、WSLはデフォルトではresolv.confを毎回自動生成するので、それを抑制するために、まずwsl.confファイルを編集します。
$ sudo nano /etc/wsl.conf ← wsl.confファイルを新規作成
[sudo] password for hogehoge:
wsl.confファイルの中身は以下のように入力します。これによりresolv.confファイルが自動で更新されるのを抑制できます。
[network]
generateResolvConf = false
続いて、resolv.confファイルを手動で作成します。
$ sudo rm /etc/resolv.conf
$ sudo nano /etc/resolv.conf
nameserver 8.8.8.8
google.comへのpingが通れば成功です。
$ ping google.com -c 1
PING google.com (172.217.161.78) 56(84) bytes of data.
64 bytes from(以下略)
Ubuntu 22.04へのアップグレード
DNS名前解決できるようになりましたので、Ubuntuのアップグレードが可能になりました。
まず、apt updateとapt upgradeコマンドを入力して、20.04の最新状態へ更新します。
$ sudo apt update ← 最新パッケージ読み込み
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
...(略)...
Reading package lists... Done
Building dependecy tree
Reading state information... Done
278 packages can be upgraded. Run 'apt list --upgradable' to see them.
$ sudo apt upgrade ← 最新パッケージへの更新
Reading package lists... Done
Building dependecy tree
Reading state information... Done
Calculating upgrade... Done
...(略)...
278 upgraded, 32 newly installed, 0 to remove and 0 not upgraded.
Need to get 174 MB of archives.
After this operation, 305 MB of additional disk space will be used.
Do you want to continue? [Y/n] y ← 更新確認にyを入力
...(略)...
$ exit ← いったんUbuntuから抜ける
最新状態への更新が終わったら、いったんUbuntuを再起動します。PowerShellから以下のコマンドを実行します。
> wsl --shutdown ← WSLをいったん終了
> wsl ← WSLを再起動
いよいよ、Ubuntuコンソールで、20.04を22.04にアップグレードします。いったん、アップグレードを開始すると、少々時間がかかり途中キャンセルできないけど続けますかと聞かれますので、yと答えます。
$ sudo do-release-upgrade ← 最新のディストリビューションに更新
...(略)...
Installing the upgrade can take several hours. Once the download has
finished, the process cannot be canceled.
Continue [yN] Details [d] y ← 処理を続行するか聞かれるのでyを入力
Fetching
...(略)...
Building dependency tree
Reading state information... Done
Searching for obsolete software
Reading state information... Done
Remove obsolete packages?
70 packages are going to be removed.
Continue [yN] Details [d] y ← 使わないパッケージ消していいか聞かれるのでyを入力
...(略)...
System upgrade is complete.
Action required
Exit all other instances of Ubuntu WSL before continuing.
Unsaved progress may otherwise be lost.
To continue please press [ENTER] ← ENTERキーを入力
WSL restart required
Exit this instance of Ubuntu WSL.
The upgrade will then be complete.
To continue please press [ENTER] ← ENTERキーを入力
...(略)...
$ exit ← いったんUbuntuから抜ける
再びUbuntuを再起動します。PowerShellから以下のコマンドを実行します。
> wsl --shutdown ← WSLをいったん終了
> wsl ← WSLを再起動
WSL用の対処
WSLでUbuntu 22.04を稼働させる際に、サポートしていない機能への対処などいくつか必要な作業があります。
needrestart
パッケージをインストールした際の再起動の判定などを行うneedrestartパッケージが、WSLでは正常に動作しません。
したがって、以下のようにneedrestartの設定を2か所変更します。
$ sudo nano /etc/needrestart/needrestart.conf
...(略)...
#$nrconf{kernelhints} = -1; ← この行の下に
$nrconf{kernelhints} = 0; ← この行を追加
...(略)...
#$nrconf{ucodehints} = 0; ← この行の下に
$nrconf{ucodehints} = 0; ← この行を追加
...(略)...
iptables
WSLではnftablesをサポートしていないので、iptablesをlegacyモードに変更します。
$ sudo update-alternatives --config iptables
There are 2 choices for the alternative iptables (providing /usr/sbin/iptables).
Selection Path Priority Status
-----------------------------------------------------------
* 0 /usr/sbin/iptables-nft 20 auto mode
1 /usr/sbin/iptables-legacy 10 manual mode
2 /usr/sbin/iptables-nft 20 manual mode
Press <enter> to keep the current choice[*], or type selection number: 1 ← 1を入力
update-alternatives: using /usr/sbin/iptables-legacy to provide /usr/sbin/iptables (iptables) in manual mode
起動時のエラー
WSLのUbuntu-20.04にあるバグで、起動時にPermission deniedのエラーがでることがあります。それを避けるために以下のコマンドでファイルを削除します。
$ sudo rm /var/lib/ubuntu-release-upgrader/ubuntu-release-upgrader
landscapeの削除
Ubuntu-22.04のlandscape機能が原因で起動時にエラーが出ることがあります。
/etc/update-motd.d/50-landscape-sysinfo: 17: cannot create /var/lib/landscape/landscape-sysinfo.cache: Permission denied
landscape機能は使わないので削除してしまいます。
$ sudo apt remove landscape-core
systemd
WSLでは、Windowsとの相互運用を行うためのプロセスがPID=1で動作しており、そのため、systemctlを実行するためのsystemdが作動していません。
さまざまな方法がネットには上がっていますが、Ubuntu 22.04では、WSLでsystemdを動作させるためのスクリプトwsl-systemdが用意されており、これを起動時に実行させることにします。
Windows11では、wsl.confに[boot]セクションが用意されておりこれを使えば良いのですが、Windows10では起動プロセスに紛れ込ませることになります。
まず、起動時に実行するスクリプトを新規に作成します。
$ sudo nano /etc/profile.d/00-wsl-systemd.sh
SYSTEMD_PID=$(ps -fe | grep '/lib/systemd/systemd --unit=multi-user.target$' | grep -v unshare | awk '{print $2}')
if [ -z "$SYSTEMD_PID" ]; then
sudo /usr/libexec/wsl-systemd
fi
スクリプト内のwsl-systemdを実行されるときに管理パスワードを尋ねられないように、wsl-systemdをsudoersに記述します。
$ sudo nano /etc/sudoers.d/wsl-systemd
%adm ALL=(ALL:ALL) NOPASSWD: /usr/libexec/wsl-systemd
Ubuntuを再起動します。PowerShellから以下のコマンドを実行します。
> wsl --shutdown ← WSLをいったん終了
> wsl ← WSLを再起動
systemdプロセスが動いていることを確認します。
$ ps -fe | grep '/lib/systemd'
...(略)...
root 24 22 0 00:00 ? 00:00:00 /lib/systemd/systemd --unit=multi-user.target
...(略)...
nsloginすれば、systemdプロセスがpid=1で動作する環境に入ることができます。
$ /usr/libexec/nslogin
$ ps -fe | grep '/lib/systemd'
root 1 0 0 00:00 ? 00:00:00 /lib/systemd/systemd --unit=multi-user.target
...(略)...
最初からsystemd pid=1
毎回/usr/libexec/nsloginと打つのが面倒なので、bashrcにnslogin仕組みを書いてしまいます。
$ vi ~/.bashrc
...(略)...
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
↓ 追加ここから
SYSTEMD_PID=$(ps -fe | grep '/lib/systemd/systemd --unit=multi-user.target$' | grep -v unshare | awk '{print $2}')
if [ -n "$SYSTEMD_PID" ] && [ "$SYSTEMD_PID" != "1" ]; then
if [ -z "$1" ]; then
/usr/libexec/nslogin
exit
fi
fi
↑ 追加ここまで
...(略)...
これで、wslコマンド実行後は、systemdがpid=1にある状態になります。
WSLにおけるsystemdの問題
WSL上のsystemdにはいろいろ問題が発生します( https://github.com/arkane-systems/genie/wiki/Systemd-units-known-to-be-problematic-under-WSL )。
特に大きな影響はありませんが、修正しておきます。
systemd-remount-fs.service
systemd起動時に以下のエラーが発生します。
mount: /: can't find LABEL=cloudimg-rootfs
これを回避するために、fstabファイルの先頭行をコメントアウト(#)します。
$ sudo vi /etc/fstab
#LABEL=cloudimg-rootfs / ext4 defaults 0 0 ← 先頭に"#"を追加する
systemd-sysusers.service
systemd起動時に以下のエラーが発生します。
systemd-sysusers.service: Failed to set up credentials: Protocol error
これを回避するために、以下のコマンドを実行します。
$ sudo systemctl edit systemd-sysusers.service
編集画面になりますので、"Lines below this comment will be discarded"よりも上に二行追加します。
### Editing /etc/systemd/system/systemd-sysusers.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file
[Service] ← 追加する行
LoadCredential= ← 追加する行
### Lines below this comment will be discarded
...(略)...
不要サービスの停止
不要なサービスと不要モジュールの整理を行います。
$ sudo apt remove modemmanager
...(略)...
Do you want to continue? [Y/n] ← yを入力
$ sudo apt autoremove
Reading package lists.. Done
...(略)...
Do you want to continue> [Y/n] ← yを入力
ディストリビューション名の変更
今のままではディストリビューション名が"Ubuntu-20.04"なので、"Ubuntu-22.04"や別の名前に以下の方法で変更することができます。
ただし、レジストリをいじることになるので、よく分からない場合は、変更しない方が無難です。
> wsl --export "Ubuntu-20.04" D:\backup\wsl-ubuntu.tar
> wsl --import "Ubuntu-22.04" D:\wsl\wsl-ubuntu D:\backup\wsl-ubuntu.tar
> wsl --set-default "Ubuntu-22.04"
> wsl --unregister "Ubuntu-20.04"
D:\backup\wsl-ubuntu.tarは、移行用に一時的に使うファイルなので、変更後は削除してかまいません。
D:\wsl\wsl-ubuntuは、ディスクイメージになります。任意のディレクトリが指定できます。
"Ubuntu-22.04"が新しいディストリビューション名です。
なお、このままだとwslコマンドを入力したときのデフォルトログインユーザがexport-importでは保存されないため、rootがデフォルトユーザになってしまいます。
デフォルトユーザを設定するには、レジストリエディタで値を編集します。
まず、以下の場所を開きます。
\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\
この下に、ディストリビューションが格納されますが、キーがUUIDなので一目でどれが対象なのかが分かりません。対象となるディストリビューションを見つけるには、それぞれのキーを開き、DistributionNameがimportした名前のものを見つけます。
Lxss\
{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
DefaultUid REG_DWORD 0x00000000
DistributionName REG_SZ Ubuntu-22.04
DefaultUidをログインしたいユーザのuidに設定します。管理ユーザのuidは、標準通りインストールしていれば1000なので、1000を入力します (10進数で入力することを間違えなく)。
Discussion