处理一个WSL1崩溃的问题

一觉醒来,我电脑上的Linux子系统(windows subsystem of Linux)WSL1崩了。

一、问题描述

我的电脑是win10 64位家庭版22H2的系统,为了开发方便,我开启了WSL1的功能,并安装了Ubuntu 22.04发行版。昨天的时候,我的WSL1突然在毫无征兆的情况下崩溃了,终端输出如下:

1
2
3
4
(base) cyclin@DESKTOP-23BCT60:source$ Error: 0xd00002fe
Error code: Bash/Service/0xd00002fe
wsl: WSL 安装似乎已损坏
按任意键修复 WSL,或 CTRL-C 取消。

当我按下回车键以后,终端开始进入WSL升级的进度条

1
正在将适用于 Linux 的 Windows 子系统更新到版本: 2.4.12。

进度条走完以后,终端进入了WSL的界面,似乎一切正常。但是当我使用wsl指令启动另一个WSL终端实例时(调用 bash.exe ),相似的错误又出现了:

1
2
3
4
5
6
7
wsl: WSL 安装似乎已损坏 (错误代码: Bash/CallMsi/Install/REGDB_E_CLASSNOTREG)。
按任意键修复 WSL,或 CTRL-C 取消。
此提示将在 60 秒后超时。
没有注册类
错误代码: Bash/CallMsi/Install/REGDB_E_CLASSNOTREG

[已退出进程,代码为 1 (0x00000001)]

ba93278f169da353b7ab25d7182c164.png

wsl.exe 指令也崩了:

0d7ebad8f4c807effad1c8cd75a9a17.png

当我启动另一个终端实例 ubuntu2204.exe 时(即,直接调用发行版的启动指令),报错如下:

0aa9a16807ad590a9f4f649ba19358d.png

心态有点崩溃。因为我有许多要在WSL上跑的任务,WSL一崩溃,这些任务都完不成。

二、探索问题的可能原因和解决途径

首先查到的是一篇文章 《WSL使用常见问题记录》 - 1379号观察员的文章 - 知乎 。但是文章并没有提供排查问题的方法,只说“wsl 常常不知道什么原因就损坏不能使用了,这个时候最直接有效的解决方法就是完全卸载后重新安装”。

此外,还找到了一些文章或帖子,如下:

差不多可以归纳为,系统静默升级过程中不小心弄坏了WSL1的某些组件,导致WSL1注册表出问题。但这个问题似乎没有什么很好的解决方法,只能从头重装。

三、问题的解决:重装系统

如题。

(一)备份重要文件

因为我们的WSL版本为WSL1,可以通过 /mnt/ 目录实现跨文件系统访问Windows上的文件(WSL2不行,它是个虚拟机),因此我们在Windows文件系统上备份一些数据(以H盘为例)。

前面提到,当我按下回车键以后,终端开始进入WSL升级的进度条

1
正在将适用于 Linux 的 Windows 子系统更新到版本: 2.4.12。

进度条走完以后,终端能够进入WSL的界面,因此我们也用这种方法进入WSL实例,然后在实例内部进行操作。

1
2
3
4
5
6
7
mkdir /mnt/h/wsl_bkp # 在电脑的H盘新建一个文件夹,用作备份文件夹。
cp -r ~/* /mnt/h/wsl_bkp/ # 把当前用户目录下的所有文件全部复制到备份文件夹。
cp -r ~/.* /mnt/h/wsl_bkp/ # 把当前用户目录下的所有隐藏文件也复制到备份文件夹。
echo $PATH > /mnt/h/wsl_bkp/echo_PATH.list # 备份一下环境变量
apt list --installed > /mnt/h/wsl_bkp/apt_list_installed.list # 备份一下已安装程序
# 我的WSL1下面的数据主要都在home目录,因此上面的几行指令差不多够用了。
# 如果读者的WSL1数据在其他目录下也有(例如 `/var`,`/opt`),那么也要记得备份

(二)卸载WSL

去控制面板里关闭下图中的这两项windows功能(控制面板→程序→启用或关闭Windows功能)

然后重启电脑。

image.png

(三)重新安装WSL

仍然是下面这个位置,去控制面板里重新打开下图中的这两项windows功能(控制面板→程序→启用或关闭Windows功能)。

然后再次重启电脑。

image.png

重启完成后,命令行输入 wsl 应该会有反应

image.png

下面我们使用指令安装WSL1(注意,默认WSL版本为WSL2。关于WSL1和WSL2的区别,参考官方文档 《比较 WSL 版本》 。要安装WSL1,需要一些额外的步骤)。

1
2
3
4
5
wsl --list --online # 列出当前可用的Linux发行版
wsl --set-default-version 1 # 选择WSL1作为默认版本。
wsl --install # 这个指令要单独先输入一遍,我不知道为什么。运行完成需要重启电脑
# 重启完成以后运行下面的指令:
wsl.exe --install Ubuntu-22.04 --enable-wsl1 # 安装Ubuntu-22.04发行版,并开启wsl1支持

注意,上面的最后一条指令,如果没有--enable-wsl1 ,安装会失败:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
C:\Windows\system32>wsl.exe --install Ubuntu-22.04
wsl: 使用旧分发注册。请考虑改用基于 tar 的分发。
正在安装: Ubuntu 22.04 LTS
已安装 Ubuntu 22.04 LTS。
正在启动 Ubuntu 22.04 LTS...



Processing fstab with mount -a failed.
Failed to mount C:\, see dmesg for more details.
Failed to mount D:\, see dmesg for more details.
Failed to mount E:\, see dmesg for more details.
Failed to mount F:\, see dmesg for more details.
Failed to mount H:\, see dmesg for more details.

<3>WSL (10 - SessionLeader) ERROR: operator():420: getpwuid(0) failed 2
<3>WSL (10 - SessionLeader) ERROR: CreateProcessCommon:640: execvpe(/bin/sh) failed: No such file or directory
分发“Ubuntu-22.04”的安装过程失败,退出代码: 1。
错误代码: Wsl/InstallDistro/WSL_E_INSTALL_PROCESS_FAILED

如果安装成功,系统会提示重启一次电脑。重启之后,运行wslbash,就可以成功进入WSL了。

(四)一些文件的恢复

1
2
3
4
cp -r /mnt/h/wsl_bkp/*  . # 把备份的文件复制回来
cp -r /mnt/h/wsl_bkp/.* . # 包括隐藏文件,这些文件一般是一些配置文件(如`.bashrc`等)
# 关于环境变量,需要看一下/mnt/h/wsl_bkp/echo_PATH.list这个文件,然后手动修改`.bashrc`
# 关于之前安装的程序,需要看一下/mnt/h/wsl_bkp/apt_list_installed.list ,然后手动安装

以上。