所知 · 2026年3月25日 0

WSL2 镜像网络模式 (Mirror Mode) 一键配置脚本

最近返回Windows11下用WSL2+Debian折腾CLI,由于默认NAT模式有诸多问题,比如宿主的代理设置问题。镜像网络模式是最优解,便用antigravity搓了这个脚本出来,保存为ps1格式运行即可。

# =========================================================
# WSL2 镜像网络模式 (Mirror Mode) 一键配置脚本 [智能合并版]
# 解决问题:localhost 代理报错、IP 不统一、无法访问宿主机
# 特色功能:智能解析、保留原有非网络配置项、强力备份回滚
# =========================================================

$configPath = "$env:USERPROFILE\.wslconfig"
$bakPath = "$env:USERPROFILE\.wslconfig.bak"

# 预定义需要追加和管控的网络配置项
$netSettings = [ordered]@{
    "networkingMode"      = "mirrored"
    "dnsTunneling"        = "true"
    "firewall"            = "true"
    "autoProxy"           = "true"
    "localhostForwarding" = "true"
}

# --- 1. 环境清理 ---
Write-Host "正在检查环境..." -ForegroundColor Cyan
if (Test-Path "$configPath.txt") {
    Remove-Item "$configPath.txt" -Force
}

# --- 2. 交互菜单 ---
Clear-Host
Write-Host "==========================================" -ForegroundColor Magenta
Write-Host "     WSL2 镜像模式配置工具 v4.0 (智能版)" -ForegroundColor Magenta
Write-Host "==========================================" -ForegroundColor Magenta
Write-Host "当前用户: $env:USERNAME"
Write-Host "配置文件: $configPath"
Write-Host "提示信息: 请确保 WSL 已更新至最新版 (终端执行: wsl --update)" -ForegroundColor DarkCyan
Write-Host "------------------------------------------"
Write-Host "1. [追加] 智能追加配置 (追加网络项、保留原 CPU/内存 限制等)"
Write-Host "2. [回滚] 恢复还原设置 (完美回滚至上一次的备份状态)"
Write-Host "3. [一键] 更新 WSL 到最新正式版本"
Write-Host "4. [退出]"
$choice = Read-Host "`n请选择操作 [1-4]"

switch ($choice) {
    "1" {
        # 1.1 自动备份流程
        if (Test-Path $configPath) {
            Copy-Item $configPath $bakPath -Force
            Write-Host "`n[备份] 发现原有配置,已将其自动备份为 .wslconfig.bak" -ForegroundColor Cyan
        }

        # 1.2 智能解析并进行合并
        $lines = @()
        $hasWsl2Section = $false

        if (Test-Path $configPath) {
            # 使用 .NET 底层读取可应对带有/不带有 BOM 的标准文件,最精确
            $existingContent = [System.IO.File]::ReadAllLines($configPath)
            foreach ($line in $existingContent) {
                
                # 判断当前行是否有历史留存的网络字段残余,如果有则跳过,防止同一键名重复多次
                $skipLine = $false
                foreach ($key in $netSettings.Keys) {
                    if ($line -match "^\s*$key\s*=") {
                        $skipLine = $true
                        break
                    }
                }
                
                if (-not $skipLine) {
                    $lines += $line
                    
                    # 侦测到存在 [wsl2] 标记了,就紧跟着注入我们的网络配置项
                    if ($line -match "^\s*\[wsl2\]") {
                        $hasWsl2Section = $true
                        foreach ($key in $netSettings.Keys) {
                            $lines += "$key=$($netSettings[$key])"
                        }
                    }
                }
            }
        }

        # 1.3 若全篇都没有 [wsl2] 这个小节头(比如空配置,或者被用户删了),那就在文件最后新建
        if (-not $hasWsl2Section) {
            # 如非首部追加个空行稍微美观一下
            if ($lines.Count -gt 0 -and $lines[-1].Trim() -ne "") {
                $lines += ""
            }
            $lines += "[wsl2]"
            foreach ($key in $netSettings.Keys) {
                $lines += "$key=$($netSettings[$key])"
            }
        }

        # 1.4 回写文件。使用带有完整签名的 UTF-8 编码写入,100% 避免终端解析乱码报错。
        $Utf8WithBom = New-Object System.Text.UTF8Encoding $true
        [System.IO.File]::WriteAllLines($configPath, $lines, $Utf8WithBom)
        
        Write-Host "`n[成功] 配置文件已更新并且旧配置已被智能保留!" -ForegroundColor Green
        Write-Host "当前生效配置内容预览:" -ForegroundColor Gray
        Write-Host "----------------"
        Get-Content $configPath
        Write-Host "----------------"
        
        Write-Host "`n正在强制重启 WSL 服务..." -ForegroundColor Yellow
        wsl --shutdown
        Write-Host "`n[完成] 请重新打开终端,网络报错应当已消失。" -ForegroundColor Green
    }
    
    "2" {
        # 智能回滚:如果备份存在,就还原备份;如果本来就没有备份,就直接清空当前网络配置(删除文件)。
        if (Test-Path $bakPath) {
            Copy-Item $bakPath $configPath -Force
            Write-Host "`n[成功] 已从原备份文件 (.bak) 无损还原环境配置!" -ForegroundColor Green
        } else {
            if (Test-Path $configPath) {
                Remove-Item $configPath -Force
                Write-Host "`n[成功] 未找到配置备份 (.bak),已直接移除当前的配置回退原本状态。" -ForegroundColor Green
            } else {
                Write-Host "`n[提示] 未发现任何配置或备份,环境已经是原样,无需回滚。" -ForegroundColor Yellow
            }
        }
        wsl --shutdown
    }
    
    "3" {
        Write-Host "`n正在检查并更新 WSL,请稍候..." -ForegroundColor Yellow
        wsl --update
        Write-Host "`n[完成] 更新操作结束。" -ForegroundColor Green
    }
    
    "4" {
        return
    }
    
    default {
        Write-Host "`n[错误] 无效选择,未执行任何操作。" -ForegroundColor Red
    }
}

Write-Host "`n按任意键退出..."
$null = [Console]::ReadKey($true)