开发机操作系统基线:Windows、macOS、Linux 与 WSL
从“同一份代码只在我这里失败”开始
一台电脑能打开终端,不等于它已经具备稳定的开发环境。构建工具实际面对的是操作系统版本、CPU 架构、进程架构、文件系统语义和当前用户权限的组合。任何一项与项目假设不一致,都可能让原生依赖安装失败、文件监听失效,或者让同名文件在本机与 Linux CI 上表现不同。
先不要急着重装工具。使用日常普通账号,在一个不含真实凭证、可以随时删除的临时目录中完成第一次探测;安装系统组件时再按动作提权。磁盘至少预留能够容纳项目依赖和验证产物的空间,计划启用 WSL 或容器时还要单独估算虚拟磁盘与镜像增长。企业设备上的代理、磁盘加密、终端安全和管理员策略不明确时,先向设备 owner 确认,避免把组织策略误判成系统故障。
操作系统升级、磁盘分区和 WSL 导入导出之前,重要文件必须已有独立备份。源码远端仓库、依赖缓存和本地数据库是三类不同资产:源码应可从远端恢复,依赖应可重建,本地数据则要有明确的导出与销毁方式。
排障时先建立四个概念:
| 对象 | 回答的问题 | 常见误判 |
|---|---|---|
| 操作系统版本 | 当前平台是否仍受支持 | 只记录“Windows”或“Ubuntu” |
| 机器架构 | CPU 原生执行什么指令集 | 把 Arm64 机器当成普通 x64 |
| 进程架构 | 当前终端或 IDE 实际以什么架构运行 | 机器是 Arm64,就认定所有子进程都是 Arm64 |
| 文件系统与挂载 | 大小写、权限、监听、性能由谁决定 | 把 WSL 的 /mnt/c 当成原生 Linux 文件系统 |
这四项先形成“机器身份”,后续语言运行时、IDE、容器和构建工具才有稳定落点。新人依靠它判断为什么失败,团队负责人则用它建立支持矩阵、例外期限和升级回退路径。
选择并启用操作系统入口
Windows
新开发机不应继续以普通 Windows 10 22H2 作为推荐基线,Microsoft 已发布其支持结束公告;LTSC、LTSB 与 ESU 则必须按具体版本和授权分别判断,不能套用普通版本结论。选择 Windows 11 时,先根据 Windows 11 生命周期 确认 edition、version、OS build 与版本通道,再核对企业镜像、硬件兼容、磁盘加密和补丁策略。系统镜像只从 Microsoft 或组织软件分发渠道获取,不使用第三方“精简版”。
安装完成后先运行 winver,再用 PowerShell 读取可记录字段:
Get-ComputerInfo |
Select-Object WindowsProductName, WindowsVersion, OsBuildNumber, OsArchitecture
[System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
[System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitectureOSArchitecture 与 ProcessArchitecture 不一致不一定是故障,但必须能解释:例如 Arm64 Windows 上运行了 x64 终端或工具。原生扩展、虚拟化、容器镜像和驱动相关工具不能仅凭“程序能启动”判定兼容。
WSL
WSL 是 Windows 上的 Linux 开发环境,不是另一台无需治理的服务器。符合 WSL 安装条件 的 Windows 可在管理员 PowerShell 中执行:
wsl --install
wsl --list --online第一条命令可能要求重启;可安装发行版必须以第二条命令的实时结果为准。完成后验证:
wsl --version
wsl --status
wsl -l -v团队要明确发行版名称、WSL 版本、源码存放位置和备份策略。主要由 Linux 工具构建的项目优先放在 WSL 的 Linux 文件系统,例如 ~/workspace;不要默认长期放在 /mnt/c 后仍能获得相同的文件监听、权限、大小写和 I/O 表现。WSL 文件权限 说明 Windows 文件访问仍受 Windows 权限上限约束,WSL 大小写规则 也说明 NTFS 挂载目录与 Linux 文件系统并非同一种语义。
跨系统访问 Linux 文件使用 \\wsl$ 或 \\wsl.localhost。不要直接操作 WSL 虚拟磁盘中的内部文件,也不要把虚拟磁盘本身当作源码备份。
macOS
安装前按 Apple 的 Mac 芯片识别方法 在“关于本机”确认型号与 macOS 版本,再用命令确认架构:
sw_vers
uname -m
sysctl -n sysctl.proc_translated 2>/dev/null || trueApple silicon 上应优先安装原生 Arm64 或 Universal 构建。Apple 对 Rosetta 与应用架构 的说明表明它承担的是 Intel 应用转译,不是所有插件、原生模块和子进程的永久兼容承诺。终端、IDE、包管理器和构建进程如果混用架构,依赖目录可能被不同二进制格式交叉污染。
Linux
“安装 Linux”不是一个统一步骤。先选择团队支持的发行版、版本、CPU 架构和桌面/服务器形态,再从发行版官方渠道获取镜像。例如 Ubuntu 的 支持架构 与 桌面安装步骤 分别回答硬件支持和安装流程;镜像名称、支持周期和架构范围会变化,支持矩阵应记录版本通道,不固定某个下载文件名。
安装后执行:
uname -srm
uname -m
cat /etc/os-release
getconf LONG_BIT
id日常开发使用普通账号,只在单个需要修改系统状态的命令前使用 sudo。不要把长期 root shell 当作“省事”的开发入口,否则依赖缓存和工作区文件会逐渐变成 root 所有,普通账号随后无法更新或清理。
先确定支持矩阵
操作系统基线不是“大家喜欢什么就装什么”,也不是强制所有人使用同一台电脑。它应描述团队承诺支持的组合:
developmentMachineBaseline:
windows:
editions: ["Windows 11 Pro", "Windows 11 Enterprise"]
architectures: ["x64", "Arm64"]
wslPolicy: "按项目启用,Linux 工具链项目优先使用 WSL 2 Linux 文件系统"
macos:
architectures: ["arm64", "x86_64"]
policy: "优先原生或 Universal 工具"
linux:
distributions: ["由团队发布支持版本,不在项目模板写死最新版"]
privilege:
dailyUser: "standard"
elevation: "per-action"这只是格式示例,不是当前版本承诺。真实文件还应包含 owner、复核日期、退役日期、已知例外和升级窗口。
工作区与文件系统
项目目录应根据主要工具链选择:
Windows 原生工具链优先使用 NTFS 本地目录,避免网络盘和同步盘承载高频依赖目录。WSL/Linux 工具链优先使用 WSL Linux 文件系统中的 ~/workspace。macOS 项目要验证默认大小写行为与 CI/Linux 是否一致,尤其是只修改文件名大小写的提交。
Linux 项目要记录工作区所在文件系统与挂载选项,不把容器挂载、网络文件系统和本地磁盘视为等价。
在目标目录运行:
pwd
df -T .
mount | headmacOS 可使用:
pwd
df -h .
mount | headWindows 可记录卷与文件系统:
Get-Volume | Select-Object DriveLetter, FileSystem, HealthStatus, SizeRemaining
Get-Location权限模型
基线遵循“日常普通用户,动作级提权”:
安装系统功能、驱动或修改系统级配置时按需提权。项目源码、依赖缓存和构建输出由日常用户拥有。不通过关闭 UAC、长期 Administrator/root、全盘 chmod 777 或递归修改系统目录解决权限问题。
WSL 的 Windows 挂载目录仍受 Windows ACL 约束;默认情况下 Linux mode bits 不能突破 Windows 权限。团队脚本只检查完成动作所需权限,不把“必须管理员运行”设为默认入口。
最小验证要证明“系统身份、架构、文件系统和权限符合项目假设”,不是证明命令能输出文字。
Windows 与 WSL 验证
Get-ComputerInfo |
Select-Object WindowsProductName, WindowsVersion, OsBuildNumber, OsArchitecture
[System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
[System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture
whoami
Get-Location
Get-Volume | Select-Object DriveLetter, FileSystem, SizeRemaining
wsl --status
wsl -l -v进入目标 WSL 发行版后:
uname -srm
uname -m
cat /etc/os-release
id
printf 'home=%s\n' "$HOME"
pwd
df -T .
touch .baseline-write-test
rm .baseline-write-testmacOS 验证
sw_vers
uname -m
sysctl -n sysctl.proc_translated 2>/dev/null || true
id
printf 'home=%s\n' "$HOME"
pwd
df -h .
touch .baseline-write-test && rm .baseline-write-testLinux 验证
uname -srm
uname -m
cat /etc/os-release
getconf LONG_BIT
id
printf 'home=%s\n' "$HOME"
pwd
df -T .
touch .baseline-write-test && rm .baseline-write-test成功标准:
OS edition、version、build 和支持状态可被记录。机器架构与当前进程架构一致,或转译关系有明确原因。当前日常账号不是长期 root/Administrator。
项目目录可由当前用户创建和删除文件,owner 没有被提权操作污染。文件系统位置符合主要构建工具链;WSL 项目明确位于 Linux 文件系统还是 Windows 挂载盘。临时验证文件已经删除,没有遗留系统设置或测试账号。
项目不应把整个操作系统镜像提交到仓库,而应提交“环境契约”和可重复探测脚本:
docs/development/
supported-platforms.md
scripts/environment/
inspect.ps1
inspect.sh
.editorconfig
.gitattributessupported-platforms.md 记录支持平台、架构、文件系统位置、例外和 owner;探测脚本只读取状态,不修改系统。.editorconfig 与 .gitattributes 约束换行符、文本属性和大小写相关协作,但不能修复底层文件系统不一致。
项目启动脚本应在真正安装依赖前输出:
OS 和发行版;机器与进程架构;当前用户;
工作区真实路径和文件系统;关键磁盘剩余空间;是否在 WSL、容器或转译进程中。
发现不支持组合时应给出可执行提示,例如“当前仓库在 /mnt/c,推荐迁移到 ~/workspace”,而不是笼统报“环境错误”。允许例外时,把例外、风险和到期时间记录在项目文档中。
识别当前上下文
Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, OsBuildNumber
[System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
[System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture
whoamiuname -srm
cat /etc/os-release
id
pwd
df -T .查看 WSL 状态
wsl --status
wsl --version
wsl -l -v
wsl --shutdownwsl --shutdown 会停止所有运行中的发行版与 WSL 2 轻量虚拟机。执行前确认没有未保存任务,不要把它当作每次故障的第一反应。
验证大小写差异
在临时目录中创建仅大小写不同的文件名,观察当前文件系统是否允许并确认 Git 状态。不要在真实源码目录直接实验:
tmp_dir="$(mktemp -d)"
cd "$tmp_dir"
touch CaseProbe caseprobe
ls -la
cd - >/dev/null
rm -rf "$tmp_dir"如果只出现一个文件,说明当前文件系统或挂载的大小写语义与 Linux CI 可能不同。团队应修复命名冲突,而不是要求所有开发者切换到某个危险的全局设置。
安装包能运行,但原生依赖构建失败
应用本身能启动,安装原生模块、编译扩展或构建容器时报告架构不匹配。
同时检查机器架构、终端进程架构、运行时架构与依赖二进制架构。
Arm64 机器上混入 x64 转译进程,或依赖缓存由另一架构生成。
统一原生工具链,删除可重新生成的架构相关缓存后重装;确需转译时将其作为显式支持组合。
新终端中重新输出进程架构并构建最小原生依赖。
WSL 中 chmod 成功,操作仍然被拒绝
mode bits 看似已经放宽,访问 /mnt/c 下文件仍失败。
确认路径是否位于 DrvFS,检查 Windows ACL 与 WSL metadata 配置。
Windows 挂载目录的权限上限仍由 Windows ACL 决定。
在 Windows 侧授予正确的最小权限,或把 Linux 工具链项目迁到 WSL Linux 文件系统。
用日常账号创建、修改、删除临时文件,不使用 sudo。
Git 只修改文件名大小写却没有得到预期结果
Windows/macOS 本地看不到重命名,Linux CI 出现重复文件或导入失败。
检查文件系统大小写语义、Git 索引和仓库中实际路径。
开发机与 CI 文件系统语义不同。
通过中间临时名称完成受控重命名,并在 CI 中增加大小写冲突检查。
在大小写敏感环境检出全新工作区并运行构建。
普通用户突然无法清理依赖目录
安装或构建成功后,普通账号无法覆盖、升级或删除文件。
检查目录 owner、ACL 与最近是否使用管理员/root 执行项目命令。
提权过程在工作区或缓存中创建了高权限所有者文件。
确认目标目录后恢复正确 owner/ACL;不要对磁盘根目录递归执行权限命令。
普通账号完成安装、构建和清理闭环。
WSL 构建慢、文件监听丢事件
大量小文件安装明显变慢,热更新偶发失效。
检查项目是否位于 /mnt/c,比较同一项目在 ~/workspace 的最小基准。
跨 Windows/Linux 文件系统访问路径带来额外语义与 I/O 成本。
把主要由 Linux 工具使用的仓库放入 WSL Linux 文件系统,通过 \\wsl.localhost 访问。
重新安装依赖并验证文件监听,记录可复现差异。
安装系统、WSL 发行版和更新可能受企业代理、软件分发和终端安全策略控制。不要为了下载成功关闭 TLS 校验、禁用安全软件或从未知镜像获取系统组件。基线至少要记录“谁提供代理、谁提供根证书、失败去哪里取证”,让后续网络与证书诊断拥有可追踪入口。
操作系统基线本身不需要业务凭证。探测脚本不得读取或输出浏览器 Cookie、SSH 私钥、云密钥、令牌和完整环境变量。设备序列号、用户名、主机名和企业域信息也可能是敏感资产,提交验收证据前应脱敏。
权限底线:
日常开发不使用长期管理员/root 会话。不以关闭 UAC、Gatekeeper、SELinux 或 TLS 校验作为通用排障步骤。不对整个磁盘执行递归 chmod、chown 或 ACL 重置。
WSL 与宿主共享目录遵循两侧权限上限,不把 777 当作可移植方案。系统安装权限与项目发布权限分离,拥有本机管理员权限不代表拥有生产系统权限。
团队应维护一份可审计的开发机支持矩阵,而不是口头约定:
| 治理项 | 最低证据 |
|---|---|
| 支持平台 | edition/distribution、version、architecture、退役日期 |
| 文件系统 | 推荐工作区位置、大小写要求、WSL 挂载边界 |
| 权限 | 日常用户、提权入口、例外审批、owner |
| 更新 | 安全补丁责任、功能升级窗口、回滚或重装路径 |
| 验收 | 探测脚本输出、项目最小构建、清理结果 |
| 退出 | 换机、离职、设备回收、WSL 数据与本地缓存清理 |
支持矩阵至少每季度复核一次,也应在操作系统停止支持、CPU 架构切换、企业镜像变更或关键工具停止兼容时触发复核。团队不能因为某台旧机器还能运行,就继续把已经结束常规支持的系统当作默认基线。
新人验收不要只截“安装成功”页面。应提交脱敏后的版本、架构、文件系统、普通用户、项目构建与清理证据。架构师关注的不是桌面外观一致,而是项目契约是否能跨受支持组合复现。
支持的是组合,不是操作系统名称
“支持 Windows”没有可执行意义。Windows 11 x64 原生、Windows 11 Arm64 上的 x64 转译、Windows + WSL 2,以及不同文件系统位置都是不同组合。判断是否纳入支持矩阵,要看关键运行时、原生扩展、容器、IDE、VPN 和企业安全软件能否一起通过最小项目闭环。
例外组合必须有 owner、已知风险和退出日期。否则团队会在每次依赖升级时重复支付兼容成本。
WSL 是双边系统,不是路径别名
同一文件从 Windows 与 Linux 访问时,会跨越权限、大小写、文件监听、换行符和性能边界。发生问题时先记录真实路径、挂载类型和操作发生在哪一侧,再讨论工具配置。把仓库从 /mnt/c 移到 ~/workspace 是架构选择,不是“神秘优化”。
WSL 2 虚拟磁盘会随数据增长,删除文件也不必然立即归还宿主空间。团队必须为源码远端、可重建依赖、本地数据库、磁盘预警、导出与重建分别定策略,不能把整个发行版当作不可替代资产。
转译层会把兼容问题推迟暴露
Rosetta 或 Windows 的架构兼容能力可以让 GUI 工具先启动,却可能在插件、编译器、子进程和原生依赖处失败。团队验收应同时记录机器、父进程、运行时和构建产物架构。发现不同架构生成同一缓存目录时,优先隔离缓存或统一原生工具链。
提权污染比安装失败更难发现
一次 sudo npm install 或管理员终端构建可能暂时成功,却把不可写文件留给后续普通用户。权限修复必须先限定目录、确认 owner 与用途,再最小化调整;禁止从磁盘根目录递归修改。真正的成功标准是普通用户能重复执行安装、构建、测试和清理。
基线升级必须有证据与回退
操作系统升级可能改变证书库、虚拟化、文件系统驱动、Shell 默认行为和安全策略。团队应先在代表性硬件上验证关键项目,再分批升级;记录升级前版本、关键构建结果、数据备份和可接受的回退方式。无法原地降级时,回退可能意味着重装,因此开发数据必须可恢复、项目依赖必须可重建。
已记录 OS edition/distribution、version、build 和支持状态。已区分机器架构与当前进程架构,转译关系可解释。当前系统版本、镜像和支持周期按执行时的官方资料复核。
Windows 10 旧基线没有因“还能启动”继续作为默认推荐。WSL 发行版和 WSL 版本通过 wsl -l -v 实测。项目位于符合主要工具链预期的文件系统。
WSL 项目明确区分 Linux 文件系统与 /mnt/c 挂载目录。已验证大小写、权限、文件监听和 I/O 的项目相关差异。日常开发使用普通用户,仅按动作提权。
工作区、依赖缓存和构建输出没有被 root/Administrator 污染。探测脚本不输出真实凭证、完整环境变量或未脱敏设备信息。项目仓库记录支持矩阵、例外、owner 和退役日期。
操作系统升级有代表性项目验证、数据备份和回退判断。WSL 数据、缓存与本地数据库有容量、清理和重建策略。已完成创建、构建或写入、清理的普通用户最小闭环。
