Windows开发环境怎么选?CMD、PowerShell与WSL2的区别及实战建议
Windows开发环境怎么选?CMD、PowerShell与WSL2的区别及实战建议
在 Windows 上进行软件开发时,我们经常会遇到一个问题:应该使用 CMD、PowerShell,还是安装 WSL2,使用 Linux 的 Bash 环境?
很多初学者一直使用 CMD,觉得它已经能够完成大部分操作;有些开发者习惯 Linux,希望在 Windows 上也使用 Bash;还有一些人安装了 PowerShell,却并不了解它与 CMD 的区别。
尤其是在使用 Codex、Git、Node.js、Python、MCP 和本地 AI Agent 等开发工具时,运行环境的选择会直接影响工具兼容性、文件访问、脚本执行和项目部署。
实际上,这三种环境各有优势,并不存在一种环境能够完全替代另外两种的情况。
本文从实际开发需求出发,介绍 CMD、PowerShell 和 WSL2 的架构、功能、命令差异、文件系统、权限管理,以及如何为 Windows AI 开发环境选择合适的工具。
一、先认识CMD、PowerShell和WSL2
首先需要明确一个概念:
CMD、PowerShell 和 WSL2 并不是完全相同层次的产品。
CMD 和 PowerShell 是 Windows 上的命令行 Shell,而 WSL2 是 Windows 提供的 Linux 运行环境。WSL2 内部还可以使用 Bash、Zsh 等 Shell。
1.1 CMD:Windows传统命令解释器
CMD 全称 Command Prompt,是 Windows 长期提供的命令行解释器。
它主要用于:
- 执行 Windows 系统命令;
- 运行
.bat、.cmd批处理文件; - 调用其他可执行程序;
- 完成简单的文件管理和系统操作;
- 维护传统 Windows 自动化脚本。
例如:
dir
查看当前目录文件。
tasklist
查看当前运行的进程。
ipconfig
查看网络接口配置。
CMD 的优点是简单、启动快、兼容性好。
很多 Windows 软件安装程序、历史运维脚本和第三方工具仍然依赖 CMD。
但是,当任务涉及复杂的数据筛选、系统管理、结构化数据处理和自动化编排时,CMD 的能力就显得比较有限。
1.2 PowerShell:面向自动化的命令行平台
PowerShell 是 Microsoft 推出的 Shell 和脚本语言。
它不仅能够执行传统 Windows 命令,还可以直接操作:
- Windows 进程;
- Windows 服务;
- 注册表;
- 文件系统;
- 网络连接;
- 用户与权限;
- .NET 对象;
- 系统管理接口。
例如:
Get-Process
查看进程。
Get-Service
查看 Windows 服务。
Get-NetTCPConnection
查看 TCP 网络连接。
Get-ChildItem
查看文件和目录。
PowerShell 最大的特点是:它的管道可以传递结构化对象,而不仅仅是文本。
这使得它非常适合编写复杂的自动化脚本。
另外,PowerShell 7 已经支持 Windows、Linux 和 macOS,不再只是 Windows 专用的命令行工具。
1.3 WSL2:在Windows中运行Linux环境
WSL2 全称 Windows Subsystem for Linux 2。
它不是简单地模拟几个 Linux 命令,而是通过轻量级虚拟机运行真正的 Linux 内核。
可以在 Windows 中安装 Ubuntu、Debian 等 Linux 发行版,使用完整的 Linux 命令行工具和开发环境。
例如:
ls -la
查看文件。
ps aux
查看进程。
ss -ltnp
查看网络监听端口。
grep -R "TODO" .
递归搜索文本。
WSL2 特别适合:
- Linux 原生开发;
- Python、Node.js 等 Linux 工具链;
- Docker 和容器开发;
- Bash 自动化;
- Linux 服务开发与部署;
- 需要接近生产 Linux 环境的项目。
1.4 三种环境的架构关系
可以通过下面这张图理解三者的区别:
图1:CMD、PowerShell 和 WSL2 的运行架构示意图。
这里还需要认识一个工具:Windows Terminal。
Windows Terminal 是终端宿主,不是 Shell。
它可以同时管理 CMD、PowerShell、WSL2、Git Bash 等环境,提供多标签页、分屏和统一的终端配置。
因此,安装 Windows Terminal 并不意味着必须使用 PowerShell,你可以在其中自由切换不同的命令行环境。
二、CMD、PowerShell与WSL2完整能力对比
了解基本定位之后,我们再从实际开发角度比较三种环境。
2.1 基础能力对比
| 对比维度 | CMD | PowerShell | WSL2 + Bash |
|---|---|---|---|
| 产品定位 | Windows 命令解释器 | Shell + 脚本语言 | Linux 运行环境 + Shell |
| 脚本语言 | Batch | PowerShell | Bash、Zsh 等 |
| 管道机制 | 主要传递文本 | Cmdlet 之间传递对象 | 主要传递文本流 |
| 文件管理 | 基础 | 丰富 | Linux 工具丰富 |
| 进程管理 | 基础 | 丰富 | Linux 原生工具 |
| Windows 服务管理 | 基础 | 原生支持 | 通过 Windows 互操作 |
| Windows 注册表 | 不方便 | 原生支持 | 通过 Windows 工具 |
| Linux 系统管理 | 不原生支持 | 可调用 WSL | 原生支持 |
| Windows 权限管理 | 基础 | ACL 集成 | Windows 文件可跨环境访问 |
| Linux 权限管理 | 不原生支持 | 不原生管理 Linux 权限 | 原生支持 |
| 网络诊断 | 基础命令 | 丰富的 Windows 网络模块 | Linux 网络工具 |
| Python 开发 | 支持 | 支持 | 支持 |
| Node.js 开发 | 支持 | 支持 | 支持 |
| Git | 支持 | 支持 | 支持 |
| Docker 工作流 | 依赖外部工具 | 依赖外部工具 | 适合 Linux 容器开发 |
| Windows API | 不方便 | 原生集成 | 需要跨环境调用 |
| 跨平台能力 | 弱 | 强(PowerShell 7+) | Linux 环境为主 |
| 典型用途 | 传统批处理 | Windows 自动化和开发 | Linux 开发与部署 |
需要注意:
- PowerShell 的对象管道主要适用于 PowerShell Cmdlet 和对象管道接收方,调用外部程序时仍然需要处理文本流和命令行参数。
- WSL2 是 Linux 运行环境,不能简单理解成 Bash 命令的集合。
- 三种环境都可以调用外部程序,但路径、参数传递、环境变量和权限可能不同。
2.2 三种环境的优缺点
CMD
优点:
- Windows 原生支持;
- 资源占用较低;
- 兼容传统批处理;
- 适合简单命令和历史脚本。
缺点:
- 复杂脚本编写不方便;
- 数据处理主要依赖文本;
- 系统管理能力有限;
- 不适合复杂自动化项目。
PowerShell
优点:
- Windows 系统管理能力强;
- 支持对象管道;
- 与 .NET 集成;
- 适合自动化和诊断工具开发;
- PowerShell 7 支持跨平台。
缺点:
- 与 Bash、CMD 的语法不同;
- 部分旧版 Windows 模块依赖 PowerShell 5.1;
- 初学者需要学习对象、管道、作用域和脚本执行机制。
WSL2
优点:
- 运行完整 Linux 内核;
- Linux 工具链兼容性好;
- 适合 Linux 服务和容器开发;
- 可以与 Windows 文件系统及程序互操作。
缺点:
- 需要管理 Linux 发行版和运行环境;
- 与 Windows 存在文件系统边界;
- 两套系统的 Python、Node.js、Git 环境需要分别管理;
- 跨文件系统访问可能产生性能损耗。
三、实际操作:相同任务,三种环境怎么实现?
这是理解三种环境最直观的方式。
下面选取日常开发中经常遇到的任务,分别使用 CMD、PowerShell 和 WSL2 实现。
3.1 查看当前目录文件
CMD:
dir
PowerShell:
Get-ChildItem
WSL2:
ls -la
三者都可以完成文件列表查询,但 PowerShell 返回的是文件和目录对象,可以进一步访问属性。
例如:
Get-ChildItem -File |
Select-Object Name, Length, LastWriteTime
可以直接得到文件名称、大小和修改时间。
3.2 查找指定文件
CMD:
dir /s /b *.ps1
PowerShell:
Get-ChildItem -Path . -Filter "*.ps1" -File -Recurse
WSL2:
find . -type f -name '*.ps1'
PowerShell 的 Get-ChildItem 可以直接返回文件对象,后续还可以继续筛选文件大小、创建时间和其他属性。
3.3 查看当前运行的进程
开发过程中,经常需要检查 Node.js、Python、Codex 或其他程序是否仍在后台运行。
三种环境都可以查看进程,但查询的范围和返回结果有所不同。
CMD:
tasklist
如果只想查看 Node.js 进程:
tasklist /FI "IMAGENAME eq node.exe"
PowerShell:
Get-Process
只查看 Node.js 进程:
Get-Process -Name node -ErrorAction SilentlyContinue |
Select-Object Id, ProcessName, CPU, WorkingSet64
PowerShell 可以直接访问进程对象的属性,例如 PID、累计 CPU 时间和工作集内存。
WSL2(Bash):
ps aux
筛选 Node.js 进程:
ps -eo pid,ppid,comm,args | grep '[n]ode'
这里有一个值得注意的区别:
WSL2 中的 ps 主要查看 Linux 进程,而 Windows 的 tasklist、Get-Process 面向 Windows 进程。
例如,在 Windows PowerShell 中启动的 node.exe,不应该假定一定能通过 WSL2 中的 ps aux 查到。
反过来,在 WSL2 中运行的 Linux Node.js 进程,也不应该简单按照 Windows 的 node.exe 进行查找。
因此,定位进程之前,首先应该确认程序实际运行在哪个操作系统环境中。
3.4 查看网络监听端口
开发本地 Web 服务、MCP Server 或调试 Python API 时,经常会遇到端口冲突。
例如:
EADDRINUSE: address already in use
假设需要排查端口 18080。
CMD:
netstat -ano | findstr ":18080"
该命令会显示包含该端口号的连接或监听项,需要进一步检查本地端口、连接状态和 PID。
PowerShell:
Get-NetTCPConnection -LocalPort 18080 -State Listen `
-ErrorAction SilentlyContinue |
Select-Object LocalAddress, LocalPort, State, OwningProcess
其中:
LocalAddress:监听地址;LocalPort:本地端口;State:连接状态;OwningProcess:对应 PID。
如果发现了监听进程,还可以进一步查询:
$targetPid = 12345
Get-CimInstance Win32_Process `
-Filter "ProcessId = $targetPid" |
Select-Object Name, ProcessId, ExecutablePath, CommandLine
注意:12345 只是示例,需要替换为实际 PID。
WSL2(Bash):
ss -ltnp
如果当前用户没有权限读取某些进程的信息,可能只能看到部分结果。在授权环境中可以进一步使用管理员权限查询。
三种环境的命令各有特点。
CMD 的 netstat 简单直接;PowerShell 更方便将端口与 Windows 进程关联;Linux 的 ss 适合检查 WSL2 或 Linux 服务器上的网络连接。
还需要注意,WSL2 与 Windows 存在不同的网络命名空间和端口转发机制。某个端口在 WSL2 中监听,不意味着 Windows 中的所有访问路径都完全相同。
3.5 搜索文件中的文本
对于软件开发来说,搜索源码比单纯查找文件更常见。
假设我们希望搜索当前项目中所有 Python 文件包含的 TODO。
CMD:
findstr /S /N /I /C:"TODO" *.py
参数含义:
/S:搜索当前目录及子目录;/N:显示匹配行号;/I:不区分大小写;/C::将指定内容作为搜索字符串。
PowerShell:
Get-ChildItem -Path . -Filter "*.py" -File -Recurse |
Select-String -Pattern "TODO" |
Select-Object Path, LineNumber, Line
PowerShell 返回的是包含文件路径、行号和匹配内容的结构化结果。
WSL2(Bash):
grep -RIn --include='*.py' 'TODO' .
Linux 的 grep 适合文本流处理,与 find、sed、awk 等工具组合使用很方便。
三者都能完成搜索任务,但 PowerShell 的结果更容易继续进行对象属性筛选和自动化处理。
另外,处理中文和 UTF-8 文件时,要注意旧版 CMD 工具对字符编码的支持可能与 PowerShell 7 或现代 Linux 工具不同。
3.6 查看与设置环境变量
环境变量是开发环境中非常重要的配置机制。
例如:
- PATH;
- JAVA_HOME;
- PYTHONPATH;
- NODE_ENV;
- 各类本地开发工具配置。
CMD:
查看 PATH:
echo %PATH%
临时设置变量:
set DEV_MODE=1
PowerShell:
查看 PATH:
$env:PATH
临时设置变量:
$env:DEV_MODE = "1"
WSL2(Bash):
查看 PATH:
printf '%s\n' "$PATH"
设置当前 Shell 及其后续子进程可继承的变量:
export DEV_MODE=1
这里需要理解一个重要概念:
Windows 环境变量与 WSL2 中的 Linux 环境变量并不是完全共享的一套配置。
Windows PowerShell 中设置的变量,不应该假定会自动出现在已经启动的 Linux Shell 中。
Linux 内部的 ~/.bashrc、~/.profile 等文件,也不会直接替 Windows PowerShell 配置环境。
WSL 提供了 WSLENV 等跨环境变量传递机制,但这属于额外的互操作配置。
对于开发项目,建议明确区分 Windows 环境配置和 Linux 环境配置,避免不同工具读取到不一致的参数。
四、PowerShell为什么适合复杂自动化?理解对象管道
如果只学习一个 PowerShell 的核心特性,我认为应该优先理解对象管道(Object Pipeline)。
这也是 PowerShell 与 CMD、Bash 的重要区别。
4.1 CMD和Bash主要处理文本
在 CMD 中:
tasklist
可以得到格式化后的进程列表。
如果继续筛选:
tasklist | findstr /I "node.exe"
findstr 处理的是前一个命令产生的文本。
Bash 中也有类似方式:
ps aux | grep '[n]ode'
这种文本管道很灵活,特别适合处理日志、配置文件和标准输出。
但如果需要提取某个进程的具体内存值,通常还要根据文本格式进行解析。
4.2 PowerShell管道能够传递对象
PowerShell 可以直接执行:
Get-Process |
Where-Object { $_.WorkingSet64 -gt 300MB } |
Select-Object ProcessName, Id, WorkingSet64
这段代码的含义是:
Get-Process获取进程对象;Where-Object根据内存属性筛选;Select-Object选择需要显示的字段。
不需要解析进程列表中的列宽或空格。
例如,查询内存占用最高的五个进程:
Get-Process |
Sort-Object WorkingSet64 -Descending |
Select-Object -First 5 `
ProcessName,
Id,
@{
Name = "MemoryMB"
Expression = {
[math]::Round($_.WorkingSet64 / 1MB, 1)
}
}
这个命令可以直接得到进程名称、PID 和内存大小。
其中的 WorkingSet64 表示进程工作集内存,并不等于程序占用的全部内存,也不应该直接理解为独占物理内存。
4.3 PowerShell对象管道的工作过程
图2:PowerShell 对象管道的数据处理过程。
4.4 如何知道一个对象有哪些属性?
可以使用 Get-Member:
Get-Process |
Select-Object -First 1 |
Get-Member
它会显示对象类型、属性和方法。
例如:
Get-Process |
Select-Object -First 1 |
Get-Member -MemberType Property
这对于学习 PowerShell 非常重要。
很多时候不需要去搜索某个工具的所有参数,只需要先获得对象,再通过 Get-Member 查看可以使用哪些属性。
还有一个实际开发习惯值得注意:
在需要继续处理结构化结果时,不要过早使用 Format-Table。
Format-Table 适合最终显示,但它会将对象转换为格式化输出对象,不适合再直接访问原始对象属性。
4.5 PowerShell调用外部程序时需要注意什么?
PowerShell 并不是所有管道都天然传递结构化对象。
例如:
git status
或者:
node.exe --version
这些都是外部程序。
它们通过标准输出返回的内容通常仍然是文本。
PowerShell 可以处理这些文本,但不会自动将 Git 输出转换成完整的 Git 状态对象。
因此,实际开发中需要区分:
- PowerShell Cmdlet:通常返回结构化对象;
- 外部可执行程序:通常通过标准输出和标准错误输出交换文本或字节数据。
这也是为什么学习 PowerShell 时,除了对象管道,还需要理解外部命令调用、参数传递和退出码。
五、Windows与WSL2文件系统有什么区别?
选择 PowerShell 还是 WSL2,往往不仅取决于命令习惯,更取决于项目存储在哪里。
5.1 Windows路径与Linux路径不同
例如,Windows 中的项目:
D:\Projects\codex-lab
在默认的 WSL2 驱动器挂载配置下,通常可以通过:
cd /mnt/d/Projects/codex-lab
访问。
而 Linux 自身的项目路径通常类似:
/home/user/projects/codex-lab
Windows 可以通过 WSL 提供的 UNC 路径访问 Linux 文件,例如:
\\wsl$\Ubuntu\home\user\projects\codex-lab
其中发行版名称和用户名必须替换为实际值。
如果需要转换路径,可以在 WSL2 中使用:
wslpath 'C:\Windows\Temp'
或者:
wslpath -w ~/projects
第二条命令要求对应目录已经存在。
5.2 Windows与Linux文件系统的区别
| 对比维度 | Windows 原生文件系统 | WSL2 Linux 文件系统 |
|---|---|---|
| 常见类型 | NTFS | 通常为 ext4 |
| 路径格式 | C:\Projects\App | /home/user/app |
| 路径分隔符 | \ | / |
| 文件名大小写 | 通常不区分 | 通常区分 |
| 主要权限机制 | Windows ACL | UID/GID 与 rwx |
| 文件可执行权限 | Windows 安全机制 | Linux 执行权限 |
| 常见换行符 | CRLF | LF |
| 适合的工具链 | Windows 程序 | Linux 程序 |
这里有两个经常出现的问题。
第一个是大小写。
Windows 中:
Config.json
config.json
在常见的默认 NTFS 配置中,可能无法作为两个独立文件存在。
而在 Linux 的 ext4 文件系统中,它们通常是两个不同的文件。
但 NTFS 也支持针对特定目录配置大小写敏感行为,所以这不是绝对区别。
第二个是权限。
Linux 程序可能依赖:
chmod +x script.sh
设置执行权限。
但 Windows 的 PowerShell 脚本执行策略和 NTFS ACL 不能简单用 Linux 的 chmod 概念理解。
尤其在 /mnt/c 等 Windows 挂载目录下,Linux 权限位的行为还可能受到 WSL 挂载选项影响。
5.3 为什么不建议把所有WSL2项目都放在/mnt/c?
这涉及文件系统性能。
假设在 WSL2 中运行一个 Node.js 项目:
cd /mnt/c/Projects/my-app
npm install
如果项目包含大量小文件,Linux 工具需要频繁跨 Windows/Linux 文件系统边界访问文件。
这可能产生明显的 I/O 开销。
对于主要由 Linux 工具处理的项目,更推荐:
mkdir -p ~/projects
cd ~/projects
然后将项目放到 Linux 文件系统中。
例如:
/home/user/projects/my-app
Microsoft 官方也建议:项目文件尽量与主要使用的开发工具位于相同的文件系统,以减少跨文件系统访问带来的性能损耗。
这并不意味着 /mnt/c 不能开发,而是说明项目存储位置应该由主要使用的工具链决定。
5.4 避免混用Windows与Linux依赖目录
一个常见问题是:
在 Windows 中执行:
npm.cmd install
然后在 WSL2 中进入同一个目录执行:
npm run build
某些纯 JavaScript 依赖可能没有问题,但涉及原生扩展、平台专用二进制文件时,就可能出现不兼容。
类似问题还可能发生在 Python 虚拟环境中。
因此建议:
Windows 项目使用 Windows 的 Node.js、Python 和依赖环境;WSL2 项目使用 Linux 的 Node.js、Python 和依赖环境。
不要直接把两个环境生成的 node_modules 或 .venv 当作同一套跨平台依赖目录复用。
六、Codex、Git、Node.js、Python和MCP应该使用哪个环境?
这部分是实际开发中最有价值的选择依据。
我的建议不是简单地“全部使用 PowerShell”,而是先确认项目最终运行在哪里。
6.1 Codex:由工作区和工具链决定
如果主要开发 Windows 本地项目,例如:
D:\Projects\my-agent
使用 PowerShell 运行 Windows 原生 Codex CLI 通常比较方便。
因为同一环境内可以使用:
- Windows Git;
- Windows Node.js;
- Windows Python;
- PowerShell 脚本;
- Windows 文件系统和权限接口。
但如果项目部署在 Linux,或依赖 Linux 原生程序,那么在 WSL2 中安装并运行对应环境的 Codex CLI,也可能更符合项目需求。
需要特别注意:
Codex 不要求必须使用 PowerShell。
选择 PowerShell 还是 WSL2,主要取决于要操作的项目、工具链和实际运行目标。
例如,Codex 在 WSL2 中调用的是 Linux 工具还是 Windows 工具,直接影响路径格式、权限和命令是否可用。
6.2 Git:尽量与项目运行环境一致
Git 本身可以在 CMD、PowerShell 和 WSL2 中运行。
Windows 项目:
git --version
git status
Linux 项目:
git --version
git status
虽然命令相同,但两套 Git 的配置文件、凭据管理方式和环境可能不同。
例如,Windows Git 与 Linux Git 可以分别配置:
git config --global user.name
及:
git config --global user.email
还应关注换行符设置:
git config --show-origin --get core.autocrlf
如果没有配置该选项,命令可能不会输出结果。
跨环境协作时,建议项目通过 .gitattributes 明确重要文本文件的换行符策略,而不是完全依赖每台电脑的个人 Git 配置。
6.3 Node.js:不要让两个环境的运行时混在一起
在 Windows PowerShell 中:
Get-Command node.exe -ErrorAction SilentlyContinue
node.exe --version
npm.cmd --version
在 WSL2 中:
command -v node
node --version
npm --version
这里有一个关键事实:
Windows 安装了 Node.js,不代表 WSL2 中就安装了 Linux 版本的 Node.js。
有些 WSL2 配置可能通过互操作找到 Windows 的 .exe 程序,但这不等于拥有独立的 Linux Node.js 运行时。
对于 Linux 项目,建议在 WSL2 发行版内部配置 Linux Node.js。
6.4 Python:解释器和虚拟环境应保持一致
Windows:
Get-Command python.exe -ErrorAction SilentlyContinue
python.exe --version
WSL2:
command -v python3
python3 --version
如果创建 Python 虚拟环境:
Windows:
python.exe -m venv .venv
WSL2:
python3 -m venv .venv
这两个 .venv 通常并不能互换。
Windows 虚拟环境和 Linux 虚拟环境具有不同的解释器路径、激活脚本与二进制依赖。
因此,同一个代码仓库可以跨平台维护,但虚拟环境应根据运行平台分别创建。
6.5 MCP Server:重点关注进程运行在哪里
MCP Server 可以使用不同语言开发,例如 Node.js、Python 等。
真正需要关注的是:
MCP Server 是由哪个进程启动的?它依赖哪个运行时?工作目录与配置路径是什么?
例如,一个 Windows 本地 MCP Server 可能使用:
node.exe
python.exe
而 Linux MCP Server 可能使用:
node
python3
两者在配置中可能出现完全不同的路径。
Windows:
D:\Projects\mcp-server\server.py
Linux:
/home/user/projects/mcp-server/server.py
如果 MCP 客户端运行在 Windows,而服务程序实际运行在 WSL2,就需要明确启动方式及跨环境参数、路径和通信方式。
不建议在没有明确设计的情况下,把 Windows 的路径直接写入 Linux 服务配置。
对于本地 AI Agent,最好明确每个组件的运行边界:
图3:Windows 与 WSL2 中的 AI 开发工具链划分示例。
这个图不是说两套环境不能通信,而是建议先保证每条开发链路自身一致,再通过明确的接口或互操作机制连接它们。
6.6 实际开发环境推荐表
| 开发任务 | 推荐环境 |
|---|---|
| Windows 文件与权限管理 | PowerShell |
| Windows 服务、注册表管理 | PowerShell |
| Windows 原生 Codex 项目 | PowerShell |
传统 .bat、.cmd 批处理 | CMD |
| Windows Node.js 项目 | PowerShell |
| Windows Python 项目 | PowerShell |
| Linux Python / Node.js 项目 | WSL2 |
| Linux 服务与容器开发 | WSL2 |
| Linux Shell 自动化 | WSL2 |
| Windows 原生 MCP Server | PowerShell |
| Linux MCP Server | WSL2 |
| 跨平台源码仓库 | 按主要构建和部署环境选择 |
七、Windows Terminal:如何管理多套开发环境?
如果电脑上同时使用 CMD、PowerShell 和 WSL2,我建议安装并使用 Windows Terminal 作为统一入口。
它可以在同一个窗口中管理多个 Shell。
7.1 PowerShell 5.1和PowerShell 7可以共存
Windows PowerShell 5.1 的主要程序入口:
powershell.exe
PowerShell 7 的主要程序入口:
pwsh.exe
可以通过下面的命令检查:
Get-Command powershell.exe, pwsh.exe `
-ErrorAction SilentlyContinue |
Select-Object Name, Source
在当前 PowerShell 中查看版本:
$PSVersionTable.PSVersion
PowerShell 5.1 主要用于兼容传统 Windows PowerShell 模块和基于 .NET Framework 的旧脚本。
PowerShell 7 基于现代 .NET,更适合作为新项目和跨平台开发的默认 Shell。
但某些旧模块仍可能需要 Windows PowerShell 5.1,所以没有必要为了使用 PowerShell 7 而直接删除旧版环境。
7.2 检查WSL2是否已经安装
在 PowerShell 中执行:
Get-Command wsl.exe -ErrorAction SilentlyContinue
如果 WSL 可用,可以进一步执行:
wsl.exe --list --verbose
该命令会显示已安装的 Linux 发行版及对应的 WSL 版本。
如果没有安装 WSL 或发行版,应先参考 Microsoft 官方安装指南,不要假定所有 Windows 电脑都已经具备 Linux 运行环境。
7.3 推荐的Windows Terminal配置
我建议保留四种终端配置:
Windows Terminal
│
├── PowerShell 7
│ ├── Windows 原生开发
│ ├── Codex CLI
│ ├── Git
│ ├── Node.js
│ └── Python
│
├── Windows PowerShell 5.1
│ └── 传统 Windows 管理脚本
│
├── CMD
│ └── 传统批处理与兼容性测试
│
└── Ubuntu(WSL2)
├── Bash
├── Linux Git
├── Linux Node.js
├── Linux Python
└── Linux 开发服务
Windows Terminal 支持配置默认配置文件、启动目录、命令行入口和其他选项。
日常可以让 PowerShell 7 成为默认终端,需要 Linux 工具时再打开 WSL2 标签页。
这种方式比反复修改系统默认 Shell 更简单,也方便排查不同环境之间的问题。
八、执行策略、权限与脚本安全:三种环境有什么不同?
运行开发脚本时,不仅需要考虑命令语法,还需要考虑脚本能否被允许执行。
8.1 CMD的脚本运行方式
CMD 通常使用:
.bat
.cmd
这些脚本依赖 Windows 用户权限、文件系统访问控制及组织安全策略运行。
CMD 没有与 PowerShell Execution Policy 完全相同的内置脚本策略机制。
但这并不意味着 CMD 脚本不受安全控制。
例如,Windows 仍然可能通过应用程序控制、文件权限和其他安全机制限制脚本或它们调用的程序。
8.2 PowerShell的执行策略
PowerShell 具有 Execution Policy。
可以通过:
Get-ExecutionPolicy
查看有效执行策略。
进一步:
Get-ExecutionPolicy -List
查看不同作用域的设置。
常见策略包括:
Restricted
RemoteSigned
AllSigned
Unrestricted
Bypass
这里需要注意:
PowerShell 执行策略是一种纵深防御机制,不是完整的安全边界。
因此,不能仅凭 RemoteSigned 就认定所有脚本都安全,也不能因为脚本被阻止就直接将执行策略修改为 Bypass。
对于有数字签名要求的脚本,还需要检查 Authenticode 签名及证书信任。
这些属于后续数字签名专题的内容。
8.3 WSL2的Linux权限机制
Linux 文件具有读、写、执行等权限。
例如:
ls -l script.sh
可以查看文件权限。
对于可信、已审查的脚本,可以根据需要设置执行权限:
chmod u+x script.sh
然后运行:
./script.sh
但这并不意味着脚本只要具有执行权限就可以在任何环境中运行。
还需要考虑文件系统挂载选项、Shell 解释器、Linux 用户权限,以及可能存在的安全控制机制。
8.4 Windows管理员与Linux root不是同一个概念
在 Windows 中使用管理员权限运行 PowerShell,与在 WSL2 中执行:
sudo
是两个不同的权限体系。
Windows 用户、Linux 用户、NTFS ACL 和 Linux 文件权限不能简单一一对应。
因此,不应为了解决某个权限错误,就习惯性地使用管理员权限或 sudo。
开发环境应尽量遵循最小权限原则,只在确实需要时提升权限。
九、最终选型建议:日常开发到底该怎么配置?
前面比较了大量功能,现在可以给出一个相对简单的实际建议。
9.1 首先根据项目确定环境
图4:根据实际开发任务选择 CMD、PowerShell 或 WSL2。
9.2 一套比较实用的Windows开发环境
如果主要使用 Windows 进行开发,我建议采用以下组合:
日常默认:PowerShell 7
适合:
- Windows 系统管理;
- Codex CLI;
- Git;
- Node.js;
- Python;
- 本地自动化脚本。
兼容性工具:Windows PowerShell 5.1
用于运行确实依赖旧版 Windows PowerShell 的管理模块或脚本。
保留 CMD
用于传统 .bat、.cmd 文件,以及需要检查 CMD 特有命令行为的场景。
按需安装 WSL2
如果开发 Linux 服务、容器化应用或依赖 Linux 原生工具链的项目,再使用 WSL2。
不建议仅仅为了使用几条 Linux 命令,就把所有 Windows 项目都迁移到 WSL2。
9.3 项目目录如何组织?
一种可行的方式是:
Windows 原生项目:
D:\Projects\
├── codex-lab\
├── powershell-tools\
├── windows-agent\
└── mcp-windows\
WSL2 Linux 项目:
/home/user/projects/
├── python-service/
├── linux-agent/
├── node-service/
└── mcp-linux/
这样做的主要好处是:
- 工作目录容易理解;
- 依赖环境不会无意混用;
- 文件权限边界更清晰;
- 更容易定位错误来自 Windows 还是 Linux;
- 减少跨文件系统访问导致的性能问题。
对于确实需要 Windows/Linux 共同开发的项目,可以通过 Git 仓库、编辑器的远程开发功能以及明确的跨系统接口协作,而不是随意共用依赖目录。
9.4 一个简单的开发环境检查方法
在 PowerShell 中:
Get-Command git, node, python, codex `
-All -ErrorAction SilentlyContinue |
Select-Object Name, CommandType, Source
这可以帮助确认当前 PowerShell 找到了哪些命令入口。
如果某个命令找不到,不代表整个系统没有安装该软件,也可能是 PATH 或当前运行环境不同。
在 WSL2 中:
command -v git
command -v node
command -v python3
command -v codex
这样可以分别确认 Linux 环境中的工具入口。
每次遇到“软件已经安装,但命令无法识别”的情况,首先确认自己正在使用哪个 Shell,以及该 Shell 实际调用的是哪个程序。
十、总结:不要寻找唯一最好的Shell,而要建立合适的工具组合
经过前面的比较,可以得出三个结论。
第一,CMD仍然有价值。
它适合传统 Windows 批处理、兼容性任务和简单命令执行。虽然自动化能力不如 PowerShell 丰富,但很多历史程序依然需要它。
第二,PowerShell非常适合作为Windows原生开发的默认Shell。
它能够直接管理 Windows 进程、服务、文件权限和系统配置,同时支持对象管道,非常适合编写诊断、管理和自动化脚本。
对于 Windows 上的 Codex、Git、Node.js、Python 和 AI Agent 开发,PowerShell 7 通常是一个实用的默认选择。
第三,WSL2适合Linux原生开发,而不是必须替代Windows。
当项目主要使用 Linux 工具、部署到 Linux 服务器或依赖 Linux 运行环境时,WSL2 可以提供更接近部署目标的开发环境。
但应该尽量将 Linux 项目及其依赖保存在 Linux 文件系统中,避免不必要的跨文件系统操作。
最终推荐的开发环境组合是:
Windows Terminal + PowerShell 7 + Windows PowerShell 5.1(兼容)+ CMD(兼容)+ WSL2(按需)。
其中 PowerShell 7 作为 Windows 原生开发的主要入口,WSL2 承担 Linux 开发任务。
这样既能利用 Windows 的系统管理优势,也能保留 Linux 工具链的灵活性。
后续文章
理解了为什么选择 PowerShell,下一步就是正确搭建它。
下一篇将介绍:
《PowerShell开发环境搭建与优化:5.1、7.x、PATH、Profile及UTF-8配置》
重点解决 PowerShell 版本共存、开发工具 PATH、命令入口、Profile 配置和中文编码问题。
再下一篇将进一步讨论 PowerShell 数字签名、证书信任和脚本安全分发。
参考资料
-
Microsoft:PowerShell 对象、属性和方法
https://learn.microsoft.com/powershell/scripting/learn/ps101/03-discovering-objects -
Microsoft:Windows 与 WSL 文件系统互操作
https://learn.microsoft.com/windows/wsl/filesystems -
Microsoft:WSL 开发环境配置
https://learn.microsoft.com/windows/wsl/setup/environment -
Microsoft:Windows Terminal 配置
https://learn.microsoft.com/windows/terminal/customize-settings/profile-general -
Microsoft:PowerShell 执行策略
https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_execution_policies -
Microsoft:PowerShell 字符编码
https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_character_encoding
更多推荐


所有评论(0)