ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker Desktop / WSL 启动失败排查全集:0x80070570、1603、START_PENDING、AppX 卡死一文搞定

Docker Desktop / WSL 启动失败排查全集:0x80070570、1603、START_PENDING、AppX 卡死一文搞定 本文全部脚本已开源github.com/TrueFurina/… sqlite 损坏检测 / VSS 提取 / Firefox Cookie 提取 / CDP 注入 / 优雅落盘觉得有用点个 Star ⭐适用症状Docker Desktop 引擎起不来、wsl --import报错或挂起、WSL 升级 MSI 失败、wslservice.exe卡 START_PENDING、Chrome 数据库异常清空。环境Windows 11 Docker Desktop 4.83 WSL 3.0.1。全部方案均为本人实测2026-103 个月排障实录按症状索引直接对号入座。症状速查表症状真实原因跳转Wsl/.../HCS/0x80070570导入发行版失败vhd/文件系统损坏§1WslService卡 START_PENDINGCPU0Lxss 注册表幽灵发行版键§2WSL MSI 安装卡死在最后一步DeprovisionMsix AppX 栈僵死§3MSI 报 1603/1619布局问题/事务残留§4浏览器登录态反复丢失、SQLite 库表为空文件系统层损坏§5引擎修好了但 pull 不动镜像直连 registry 被墙§61. 0x80070570文件系统损坏现象Docker 后端日志出现wsl.exe --import-in-place docker-desktop ... failed: 文件或目录损坏且无法读取。 错误代码: Wsl/Service/RegisterDistro/CreateVm/HCS/0x80070570定位0x80070570 ERROR_FILE_CORRUPT。vhd/vhdx 或其所在卷的文件系统损坏。修复:: 1. 管理员 PowerShell预约开机自检C 盘无法在线锁卷 chkdsk C: /f :: 按提示输入 Y重启。观察关键字段 :: 0 KB in bad sectors → 硬件无损纯文件系统层损坏可放心 :: 有坏簇数字 → 立即备份数据考虑换盘 ​ :: 2. 用安装包内的干净模板替换损坏的 vhdx copy /Y C:\Program Files\Docker\Docker\resources\wsl\ext4.vhdx ^ %LOCALAPPDATA%\Docker\wsl\main\ext4.vhdx ​ :: 3. SMART 佐证硬件健康与否 powershell Get-PhysicalDisk | Format-Table FriendlyName,HealthStatus注意chkdsk 通过 ≠ 万事大吉。文件系统损坏往往是连环事故的第一张多米诺后续 WSL/浏览器异常接着查。2. WslService 卡 START_PENDING现象sc query WslService显示STATE : 2 START_PENDING数小时不变服务进程 CPU0wsl.exe任何命令挂起 45s。排查顺序本人实测有效的优先级# ① 依赖服务 Get-Service vmcompute, hns # 必须 Running ​ # ② 插件目录 dir C:\Program Files\WSL\lib\ # 只有 3 个 GPU dll 是正常的 ​ # ③ ★幽灵发行版注册键本例真凶★ reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss /s # 逐个核对每个 GUID 键的 BasePath VhdFileName 指向的文件是否存在修复删掉指向不存在文件的发行版键服务卡死时wsl --unregister无效只能删注册表reg delete HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{GUID} /f taskkill /F /IM wslservice.exe sc start WslService效果wsl --version从 45s 超时 → 131ms。原理WSL 是文件 注册表双状态组件。vhd 文件删了但注册表键残留服务枚举发行版时撞上幽灵键即挂死。凡是手动删过 vhd / 重装过 Docker 的机器都要查这一步。3. MSI 卡死DeprovisionMsix现象wsl --update或手动运行 WSL 的 msi进度条卡在最后一步verbose log 尾部永远是ActionStart(NameDeprovisionMsix,,) CustomActionSchedule(ActionDeprovisionMsix,ActionType3073,...)原因该自定义动作要反预配deprovision收件箱版 WSL 的 MSIX 包但机器的 AppX 部署栈僵死——验证方法会挂起即中招Get-AppxPackage -AllUsers -Name *WindowsSubsystem* # 挂起 AppX 栈坏修复三层递进:: 第 1 层DISM 移除预配包走独立部署路径绕开僵死的 AppXSvc dism /online /Get-ProvisionedAppxPackages | findstr /i Subsystem dism /online /Remove-ProvisionedAppxPackage ^ /PackageName:MicrosoftCorporationII.WindowsSubsystemForLinux_版本_x64__8wekyb3d8bbwe ​ :: 第 2 层每用户注册的包用 DISM 删不掉 → 干净启动 :: msconfig → 服务 → 勾选隐藏所有 Microsoft 服务 → 全部禁用 → 重启 ​ :: 第 3 层干净启动下重跑 MSI一次通过 msiexec /i %TEMP%\wsl.3.0.1.0.x64.msi /l*v %TEMP%\wsl_install.log警告干净启动会禁用全部第三方服务。已知副作用浏览器登录态异常见 §5。修完后 msconfig → 常规 → 正常启动 → 再重启恢复。4. MSI 1603 / 16191603 布局陷阱从管理解包/缓存目录拿 MSI 装时必踩MSI (s): Source for file RdpWinStlHelper.dll is uncompressed, at ...\PFiles64\WSL\ MSI (s): Folder is not accessible: C:\Users\...\Downloads\PFiles64此类 MSI 的文件不内嵌 CABMSI 必须与PFiles64\WSL\文件夹同级才能安装。单独复制 MSI 到任意目录运行必然 1603。1619 安装包路径无效卸载过程会删除C:\Windows\Installer\下的缓存 MSI。卸载重装分两步跑时第二步会找不到包。对策先备份缓存 MSI或从官方 release 重下。通用诊断命令GUI 永远只说 1603真相在日志里msiexec /i xxx.msi /l*v full.log :: 在日志里搜按优先级 :: return value 3 → 第一个失败点看它前 30 行 :: Note: 1: 1714/1723/1603 :: DEBUG: Error挂起的事务清理强杀 msiexec 后安装器报当前安装处于挂起状态 (0x80070644)reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\InProgress :: 有值则删或重启SCM 会回收5. Chrome SQLite 库全空与 Cookie 迁移现象所有网站登录态丢失重新登录后重启浏览器即掉。特征性诊断结果检查项正常值受损值文件头SQLite format 3SQLite format 3照样合法sqlite_master 表数量十几个0非零字节占比60%~9%文件头合法 表结构清零 → Chrome 打开库认为正常但写入全部落空 → 登录仅存内存 → 关浏览器即蒸发。这就是怎么登都掉的机理。恢复决策树① 卷影副本恢复 vssadmin list shadows管理员 copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyN\Users\user\...\Cookies dst → 注意验证快照版本的表结构文件系统损坏往往在快照前已发生 ② 其他 Chromium 浏览器还有登录态 → Cookie 迁移下述本人验证可行的完整路径 ③ 都没有 → 只能账号找回Cookie 迁移Firefox → Chrome# Step 1: 提取Firefox 运行中库被锁复制 wal 即可读 Copy-Item $env:APPDATA\Mozilla\Firefox\Profiles\profile\cookies.sqlite D:\ff.db python -c import sqlite3; consqlite3.connect(rD:\ff.db); print(con.execute( \SELECT name,value FROM moz_cookies WHERE host LIKE %bilibili%\).fetchall()) ​ # Step 2: Chrome 新版有 App-Bound 加密Local State 密钥前缀 DPA # 直接写 Cookies 数据库的明文列会在启动时被清空 → 必须走 CDP 注入# Step 3: CDP 注入完整可运行Python websockets import subprocess, time, json, urllib.request, asyncio, websockets ​ CHROME rC:\Program Files\Google\Chrome\Application\chrome.exe # 关键默认 User Data 目录禁止开调试端口必须复制一份副本配置 UD rC:\Temp\chrome_cdp COOKIES json.load(open(bili_cookies.json)) # 含 domain/name/value/path/secure/httpOnly/expires ​ subprocess.Popen([CHROME, --remote-debugging-port9222, f--user-data-dir{UD}, --no-first-run, about:blank]) for _ in range(15): time.sleep(2) try: targets json.loads(urllib.request.urlopen( http://127.0.0.1:9222/json/list, timeout2).read()); break except Exception: pass ​ page next(t for t in targets if t[type] page) ​ async def main(): async with websockets.connect(page[webSocketDebuggerUrl], max_size10**7) as ws: mid 0 async def cmd(m, p): nonlocal mid; mid 1 await ws.send(json.dumps({id: mid, method: m, params: p})) while True: r json.loads(await ws.recv()) if r.get(id) mid: return r await cmd(Network.enable, {}) for c in COOKIES: p {name: c[name], value: c[value], domain: c[domain], path: c[path], secure: c[secure], httpOnly: c[httpOnly]} if c.get(expires): p[expires] c[expires] / 1e6 # Chrome us → CDP s await cmd(Network.setCookie, p) # 验证真实业务接口落盘前最后防线 await cmd(Page.navigate, {url: https://www.bilibili.com}) ev await cmd(Runtime.evaluate, {expression: fetch(https://api.bilibili.com/x/web-interface/nav,{credentials:include}) .then(rr.json()).then(jj.data.isLogin?LOGGED_IN:FAIL), awaitPromise: True, returnByValue: True}) print(ev[result][result][value]) ​ asyncio.run(main())# Step 4: ★优雅关闭绝不能 taskkill /F强杀不触发 Cookie 落盘 (Get-Process chrome | ForEach-Object { $_.CloseMainWindow() }) ; Start-Sleep 6 ​ # Step 5: 把临时配置的登录态拷回真实配置Chrome 必须已完全退出 Copy-Item C:\Temp\chrome_cdp\Default\Network\Cookies $env:LOCALAPPDATA\Google\Chrome\User Data\Default\Network\Cookies -Force Copy-Item C:\Temp\chrome_cdp\Local State $env:LOCALAPPDATA\Google\Chrome\User Data\Local State -Force验证重启 ChromeF12 → Application → Cookies确认 SESSDATA 存在关开浏览器不掉即成功。6. 镜像拉取加速引擎就绪后docker pull超时的最后一块拼图——直连 registry 被墙。编辑%USERPROFILE%\.docker\daemon.json{ builder: { gc: { defaultKeepStorage: 20GB, enabled: true } }, experimental: false, registry-mirrors: [ https://docker.1ms.run, https://docker.m.daocloud.io, https://dockerproxy.net ] }重启 Docker Desktop 后验证docker info | findstr -A 4 Registry docker pull hello-world → Status: Downloaded newer image附完整修复时序可直接照抄的操作顺序1. chkdsk C: /f → 重启自检 → 确认 0 bad sectors 2. reg query HKCU\...\Lxss /s → 删除指向不存在文件的发行版键 3. wsl --unregister docker-desktop 用安装包模板重新导入 4. wsl -d distro echo BOOT_OK ← 209ms 内返回才算服务健康 5. 启动 Docker Desktop → docker info 看到 Server 段即成功 6. daemon.json 加 registry-mirrors → docker pull 验证血泪经验全文浓缩GUI 错误码一文不值verbose log 才是真相MSI/l*v、Dockercom.docker.backend.exe.logWSL/MSI 这类文件注册表双状态组件挂死先查注册表残留落盘判成功CDP success ≠ 数据在磁盘taskkill /F是 Cookie 消失的头号元凶文件系统损坏是连环事故vhd、SQLite 库会接连中招修复后必须全盘体检干净启动是大杀器也是双刃剑修好了部署栈丢了浏览器登录态——用前关浏览器用后备好账号密码本文所有命令在 Windows 11 24H2 Docker Desktop 4.83 WSL 3.0.1 实测通过。转载请注明出处。附录 ASQLite 结构性损坏检测脚本§5 场景的快速定性工具——判断任意 SQLite 文件是真损坏还是表结构清零两者处置完全不同# sqlite_check.py import sqlite3, sys ​ def check(path): with open(path, rb) as f: head f.read(65536) ok_header head[:16] bSQLite format 3\x00 nonzero sum(1 for b in head if b) / len(head) print(f文件头: {head[:16]} 合法{ok_header}) print(f前64K非零字节占比: {nonzero:.1%} (30% 高度可疑)) try: con sqlite3.connect(path) tables [r[0] for r in con.execute( SELECT name FROM sqlite_master WHERE typetable)] print(f表: {tables}) except Exception as e: print(f打开失败: {e}) return False return ok_header and len(tables) 0 ​ for p in sys.argv[1:]: print(f\n {p} ) print(健康 if check(p) else ★结构性损坏表清零★)判读矩阵文件头表数量结论处置合法0健康正常使用合法0结构性损坏本案例移除重建数据无法自恢复非法-文件级损坏换文件/恢复备份Chrome 场景下批量检测python sqlite_check.py ^ %LOCALAPPDATA%\Google\Chrome\User Data\Default\Network\Cookies ^ %LOCALAPPDATA%\Google\Chrome\User Data\Default\History ^ %LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data ^ %LOCALAPPDATA%\Google\Chrome\User Data\Default\Web Data附录 B卷影副本VSS提取与验证§5 恢复决策树第一分支的完整操作。前提系统保护已开启很多机器默认只对系统盘开。:: 1. 列出快照管理员 vssadmin list shadows :: 记录 Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyN :: 注意 Creation Time —— 只有早于损坏时间的快照才有意义 ​ :: 2. cmd 提取会因路径转义失败\\?\GLOBALROOT 反斜杠被吃必须 PowerShell# vss_extract.ps1管理员运行 $src \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Users\用户名\AppData\Local\Google\Chrome\User Data\Default\Network\Cookies New-Item -ItemType Directory -Force -Path D:\recover | Out-Null try { Copy-Item -LiteralPath $src -Destination D:\recover\Cookies_snapshot -Force -EA Stop COPY_OK } catch { COPY_FAIL: $($_.Exception.Message) }:: 3. ★必做验证快照版本健康度用附录 A 脚本 python sqlite_check.py D:\recover\Cookies_snapshot :: 表为空 快照时已损坏 → 此路不通转 §5 决策树下一分支实测教训文件系统损坏是渐进的。本案例 10/5 中午的快照提取成功但快照里的库同样是空表——白高兴一场。快照越早越好。附录 CFirefox Cookie 提取脚本附去重逻辑# ff_extract.py — Firefox 多容器会产生同名 Cookie 副本必须去重 import sqlite3, json, shutil ​ # Firefox 运行中库被锁先复制连同 WAL否则可能只读到旧数据 PROF rC:\Users\用户名\AppData\Roaming\Mozilla\Firefox\Profiles\profile shutil.copyfile(PROF r\cookies.sqlite, rD:\ff.db) ​ con sqlite3.connect(rD:\ff.db) con.row_factory sqlite3.Row rows con.execute(SELECT * FROM moz_cookies WHERE host LIKE %目标域%).fetchall() ​ seen {} # (host, name, path) 三元组去重 for r in rows: seen[(r[host], r[name], r[path])] dict(r) ​ out [{ domain: r[host], name: r[name], value: r[value], path: r[path], expires: r[expiry]*1000000 11644473600000000, # Unix秒 → Chrome微秒 secure: bool(r[isSecure]), httpOnly: bool(r[isHttpOnly]), } for r in seen.values()] ​ json.dump(out, open(cookies.json, w), ensure_asciiFalse) print(f导出 {len(out)} 条)前置校验别急着迁移先确认凭证还有效import sqlite3, time con sqlite3.connect(rD:\ff.db) now time.time() for n, h, v, e in con.execute( SELECT name,host,value,expiry FROM moz_cookies WHERE name IN (SESSDATA,DedeUserID,bili_jct)): print(f{h} {n}: len{len(v)} {有效 if e now else ★已过期})附录 DAppX 栈僵死自检三连§3 的快速定性# 1. 查询挂起60s 无响应即中招 Measure-Command { Get-AppxPackage -AllUsers -Name *Subsystem* } ​ # 2. 预配包列表DISM 独立路径AppXSvc 僵死时依然可用 dism /online /Get-ProvisionedAppxPackages | findstr /i Subsystem ​ # 3. AppX 服务状态 Get-Service AppXSvc, ClipSVC, StateRepository | Format-Table Name, Status三个结果对应三种处置① 挂起 ③ Running → AppX 栈假死干净启动最稳② 有输出 → 用 DISM 删预配包§3 第 1 层② 也挂 → 只剩干净启动一条路§3 第 2 层附录 EDocker 引擎健康自检 30 秒清单# ① 三个依赖服务全 RUNNING Get-Service WslService, vmcompute, hns | Format-Table Name, Status ​ # ② 发行版列表秒回30s 回去查 §2 幽灵键 wsl -l -v ​ # ③ 发行版能启动秒回 BOOT_OK 才算健康 wsl -d docker-desktop sh -c echo BOOT_OK ​ # ④ 后端日志最新错误GUI 只会说 unable to start Get-Content $env:LOCALAPPDATA\Docker\log\host\com.docker.backend.exe.log -Tail 100 | Select-String TimedOut|failed to start|0x8 ​ # ⑤ 引擎探活有 Server 版本号 活着 docker info --format {{.ServerVersion}} {{.Driver}}附录 F本次修复全程操作时序可照抄第 1 天定性 1. chkdsk C: /f预约→ 重启自检 → 确认 0 bad sectors 2. Get-PhysicalDisk → SMART Healthy → 确认硬件无损 第 2 天重建 3. reg query HKCU\...\Lxss /s → 删幽灵发行版键§2 4. wsl --unregister docker-desktop → 模板重导入 5. wsl -d docker-desktop echo BOOT_OK209ms 服务健康 6. Docker Desktop → docker info 见 Server 段 7. daemon.json 加 registry-mirrors → docker pull hello-world 成功§6 插曲同步进行 A. Chrome 六库全空 → VSS 提取失败快照已坏→ Firefox Cookie 迁移§5 B. WSL 2.7→3.0.1 MSI 五连败 → DISM 删预配包 干净启动 → 装好§3/§4附录 A–E 脚本均为实测原样参数中的用户名/profile/GUID按机器替换。
返回列表