第 4 章 · 终端与 Shell
一句话:终端是敲命令的窗口,Shell 是解释命令的程序;本书所有命令都在这一对组合里运行。 用它还是用别的:Windows 上用 Windows Terminal 加 PowerShell 7;教程只给 Linux 命令、或项目要在 Linux 服务器上跑时,用 WSL 里的 bash;macOS 用自带终端和 zsh。 核对版本:PowerShell 7.6、Windows Terminal 1.24、bash 5.2,2026-10
4.1 安装与版本
Section titled “4.1 安装与版本”Windows:
winget install Microsoft.WindowsTerminalwinget install Microsoft.PowerShellWindows 11 已自带 Windows Terminal,可以跳过第一条。PowerShell 7 装好后,Windows Terminal 的下拉菜单里多出一个名为“PowerShell”的配置文件;名为“Windows PowerShell”的那个是系统自带的 5.1。
要在 Windows 里用 Linux,以管理员身份打开 PowerShell 运行下面这条,默认装 Ubuntu,装完要重启,完整步骤见 4.4:
wsl --installmacOS 自带“终端”应用,默认 Shell 是 zsh,不用装。想要分屏、搜索更顺手的终端,可以装 iTerm2:
brew install --cask iterm2Linux 桌面版自带终端,默认 Shell 是 bash,不用装。
查版本。PowerShell 看 Major 一列,7 才是 PowerShell 7;wsl --version 第一行是 WSL 版本:
$PSVersionTable.PSVersionwsl --versionbash --version4.2 五分钟概念
Section titled “4.2 五分钟概念”- 终端(Terminal):显示文字、接收键盘输入的窗口程序,比如 Windows Terminal、macOS 的终端、VS Code 底部的集成终端(第 1 章)。它管字体、配色、标签页和分屏,自己不认识任何命令。
- Shell:在终端里运行、真正解释你敲的命令的程序,比如 PowerShell、bash、zsh。同一个终端里可以开不同的 Shell,命令写法跟着 Shell 走,跟终端无关。
- PowerShell 7 与 Windows PowerShell 5.1:两个独立的程序,可以同时装在一台机器上。7 的程序名是
pwsh,5.1 是powershell;配置文件、已装的模块各存一份。本书的 PowerShell 命令都按 7 写,在 5.1 里个别命令会不一样,比如curl,见 4.6。 - WSL(Windows Subsystem for Linux):在 Windows 里运行一个真正的 Linux 发行版,里面是原版的 bash、apt 和 Linux 命令。Docker Desktop 在 Windows 上也靠它运行(第 12 章)。
- 环境变量与 PATH:环境变量是 Shell 传给它启动的每个程序的一组“名字=值”。其中 PATH 是一串目录,你敲
git时,Shell 按顺序在这些目录里找git程序,找不到就报“找不到命令”。 - 管道(Pipeline):用
|把前一条命令的输出交给后一条。bash 里传的是一行行文本,要靠grep、cut按列切;PowerShell 里传的是对象,可以直接按属性筛选排序,比如Get-Process | Sort-Object CPU -Descending | Select-Object -First 5列出最占 CPU 的五个进程。
三层的关系如下:终端只是外壳,换终端不换 Shell,命令写法不变;换了 Shell,同一件事的写法就变了,这正是 4.3 那张对照表要解决的事。
4.3 常用命令
Section titled “4.3 常用命令”PowerShell 7 给 ls、cat、cd、pwd、cp、mv、rm 都设了别名,不带参数时和 bash 一样用;一旦带上 -la、-rf 这种 bash 写法的参数就会报错,要换成右列的写法。bash 一列在 Linux、WSL 和 macOS 的 zsh 里都能用。Ctrl+R、Ctrl+L 在 macOS 上也是按 Ctrl,不是 Cmd。
| 任务 | bash | PowerShell |
|---|---|---|
| 文件与目录 | ||
| 看当前目录 | pwd |
pwd |
| 列出文件,含隐藏文件 | ls -la |
Get-ChildItem -Force |
| 进入目录;回到上一个目录 | cd <目录>;cd - |
cd <目录>;cd - |
| 建多级目录 | mkdir -p a/b/c |
mkdir a/b/c |
| 建空文件 | touch a.txt |
New-Item a.txt |
| 复制目录 | cp -r <源> <目标> |
Copy-Item -Recurse <源> <目标> |
| 移动或改名 | mv a.txt b.txt |
Move-Item a.txt b.txt |
| 删除目录及里面所有内容 | rm -rf <目录> |
Remove-Item -Recurse -Force <目录> |
| 看文件内容 | cat <文件> |
Get-Content <文件> |
| 看前 20 行 | head -n 20 <文件> |
Get-Content <文件> -TotalCount 20 |
| 看后 20 行 | tail -n 20 <文件> |
Get-Content <文件> -Tail 20 |
实时跟踪日志,Ctrl+C 停止 |
tail -f app.log |
Get-Content app.log -Wait -Tail 20 |
| 打包成 tar.gz | tar -czf a.tgz <目录> |
tar -czf a.tgz <目录> |
| 解开 tar.gz | tar -xzf a.tgz |
tar -xzf a.tgz |
| 查找 | ||
| 按文件名找 | find . -name "*.log" |
Get-ChildItem -Recurse -Filter *.log |
| 在所有文件里找文字 | grep -rn "TODO" . |
Get-ChildItem -Recurse -File | Select-String "TODO" |
| 在指定文件里找文字 | grep -n "TODO" *.py |
Select-String -Path *.py -Pattern "TODO" |
| 环境 | ||
| 看全部环境变量 | env |
Get-ChildItem Env: |
| 看一个变量 | echo $NODE_ENV |
$env:NODE_ENV |
| 设变量,只在当前终端有效 | export NODE_ENV=production |
$env:NODE_ENV = "production" |
| 看 PATH,一行一个目录 | echo $PATH | tr ':' '\n' |
$env:PATH -split ';' |
| 命令在哪个位置 | which git |
Get-Command git |
| 看命令帮助 | man ls |
Get-Help Get-ChildItem |
| 进程与网络 | ||
| 看进程 | ps aux | grep node |
Get-Process node |
| 按 PID 结束进程 | kill <PID> |
Stop-Process -Id <PID> |
| 按名字结束进程 | pkill node |
Stop-Process -Name node |
| 谁占用了 3000 端口 | lsof -i :3000 |
Get-NetTCPConnection -LocalPort 3000 -State Listen |
| 发 HTTP 请求 | curl -I https://example.com |
curl.exe -I https://example.com |
| 调 JSON 接口(PowerShell 直接得到对象) | curl -s <url> |
Invoke-RestMethod <url> |
| 历史与效率 | ||
| 搜索历史命令 | Ctrl+R 后输入几个字 |
Ctrl+R 后输入几个字 |
| 重新执行上一条命令 | !! |
r |
| 清屏 | clear 或 Ctrl+L |
cls 或 Ctrl+L |
| 设命令别名 | alias ll='ls -la' |
Set-Alias ll Get-ChildItem |
| 重定向 | ||
| 输出写进文件,覆盖原内容 | <命令> > out.txt |
<命令> > out.txt |
| 追加到文件末尾 | <命令> >> out.txt |
<命令> >> out.txt |
| 丢弃输出 | <命令> > /dev/null |
<命令> > $null |
| 输出和错误写进同一个文件 | <命令> > all.txt 2>&1 |
<命令> > all.txt 2>&1 |
| 只把错误写进文件 | <命令> 2> err.txt |
<命令> 2> err.txt |
几点补充:
lsof没装时,Linux 上用ss -ltnp,最后一列是占用端口的进程。PowerShell 的结果里OwningProcess一列是 PID,接着用Get-Process -Id <PID>看它是谁。- 进程与网络这几行的 bash 写法要在 WSL 或 Linux 里用;Git Bash 的
ps、kill只看得到 Git Bash 自己启动的进程。 - PowerShell 7 里
curl就是真正的 curl 程序;在 5.1 里它是另一条命令的别名,所以表里一律写curl.exe,两个版本都对。 - PowerShell 的别名只能换个名字,不能带参数;
ll想带参数,要写成函数,见 4.5。 - 在大项目里找文字,
rg比grep和Select-String快得多,两边写法相同,见第 5 章。登录远程服务器用ssh,见第 6 章。
Windows Terminal 只有 Windows 版,下面的快捷键表只适用于 Windows;macOS 终端和 iTerm2 的分屏、标签页快捷键在它们各自的菜单里能看到。
| 操作 | 快捷键 | 说明 |
|---|---|---|
| 新标签页 | Ctrl+Shift+T |
用默认配置文件,改默认见 4.4 |
| 选一个配置文件开新标签页 | Ctrl+Shift+Space |
弹出下拉菜单,PowerShell、Ubuntu 等都在里面 |
| 向右拆分窗格 | Alt+Shift++ |
新窗格和当前窗格用同一个配置文件 |
| 向下拆分窗格 | Alt+Shift+- |
一边跑服务、一边看日志时用 |
| 在窗格之间切换 | Alt+方向键 |
当前窗格有彩色边框 |
| 关闭当前窗格 | Ctrl+Shift+W |
只剩一个窗格时关掉整个标签页 |
| 设置 | Ctrl+, |
图形界面;Ctrl+Shift+, 直接打开 settings.json |
| 命令面板 | Ctrl+Shift+P |
记不住快捷键时搜操作名 |
4.4 典型工作流
Section titled “4.4 典型工作流”把 Windows Terminal 的默认 Shell 改成 PowerShell 7
Section titled “把 Windows Terminal 的默认 Shell 改成 PowerShell 7”打开 Windows Terminal 默认进的往往是 5.1,本书的命令按 7 写:
- 装 PowerShell 7:
winget install Microsoft.PowerShell。 - 关掉所有 Windows Terminal 窗口再打开,按
Ctrl+Shift+Space,确认下拉菜单里有“PowerShell”。 - 按
Ctrl+,打开设置。 - 左侧选“启动”,“默认配置文件”选“PowerShell”,不是“Windows PowerShell”。
- 点右下角“保存”。
- 按
Ctrl+Shift+T开新标签页,运行$PSVersionTable.PSVersion,Major是 7 就成功了。
VS Code 集成终端用哪个 Shell 另外设置,见第 1 章的 terminal.integrated.defaultProfile.windows。
装 WSL,在 VS Code 里打开 WSL 里的项目
Section titled “装 WSL,在 VS Code 里打开 WSL 里的项目”教程只给 Linux 命令,或项目依赖 Linux 才有的工具时,在 WSL 里开发:
- 以管理员身份打开 PowerShell,运行
wsl --install。 - 装完重启电脑。
- 重启后从开始菜单打开 Ubuntu,按提示设 Linux 用户名和密码,以后
sudo要输这个密码。 - 更新软件包:
sudo apt update && sudo apt upgrade。 - 在 Linux 家目录下建项目目录:
mkdir -p ~/projects && cd ~/projects,不要放在/mnt/c下,原因见 4.6。 - 下载项目:
git clone <url>,然后cd进项目目录。 - 在 Windows 这边给 VS Code 装 WSL 扩展(第 2 章):
code --install-extension ms-vscode-remote.remote-wsl。 - 回到 WSL 的项目目录,用 VS Code 打开:
code .。第一次会先在 WSL 里装好 VS Code 的服务端,左下角显示“WSL: Ubuntu”就对了。 - 要在 Windows 资源管理器里看这些文件:
explorer.exe .。
以后在 Windows Terminal 里按 Ctrl+Shift+Space 选“Ubuntu”,就直接进 WSL。
把一个目录永久加进 PATH
Section titled “把一个目录永久加进 PATH”$env:PATH 和 export PATH 只在当前终端有效,关掉就没了。要每次打开都有,写进 Shell 的配置文件。PowerShell:
- 看配置文件在哪:
$PROFILE。 - 文件还不存在就新建:
if (!(Test-Path $PROFILE)) { New-Item -Path $PROFILE -ItemType File -Force }。 - 用 VS Code 打开:
code $PROFILE。 - 加一行并保存:
$env:PATH += ";$HOME\tools"。 - 让当前终端立即生效:
. $PROFILE。 - 检查最后一个目录是不是它:
$env:PATH -split ';' | Select-Object -Last 1。
bash(Linux、WSL、Git Bash);macOS 的 zsh 把 ~/.bashrc 换成 ~/.zshrc:
- 追加一行到配置文件:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc。 - 让当前终端立即生效:
source ~/.bashrc。 - 检查第一个目录是不是它:
echo $PATH | tr ':' '\n' | head -3。
$PROFILE 只对 PowerShell 生效。要让 Windows 上所有程序都看到这个目录,在开始菜单搜“环境变量”,打开“编辑账户的环境变量”,在用户变量 Path 里新建一行,然后重开终端。
4.5 配置要点
Section titled “4.5 配置要点”配置文件的位置:
| 范围 | 路径 |
|---|---|
| PowerShell 7 | $HOME\Documents\PowerShell\Microsoft.PowerShell_profile.ps1,以 $PROFILE 的输出为准 |
| Windows PowerShell 5.1 | $HOME\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 |
| bash(Linux、WSL、Git Bash) | ~/.bashrc |
| zsh(macOS) | ~/.zshrc |
| Windows Terminal | %LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json |
| PowerShell 的历史记录 | %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt |
“文档”文件夹被 OneDrive 或其他盘接管时,PowerShell 配置文件的实际位置会变,所以永远以 $PROFILE 的输出为准。Windows Terminal 的配置不用记路径,按 Ctrl+Shift+, 直接打开。
值得改的项:
| 配置项 | 建议值 | 效果 |
|---|---|---|
Windows Terminal 默认配置文件(defaultProfile) |
PowerShell | 新标签页直接进 PowerShell 7,步骤见 4.4 |
Windows Terminal 字体(font.face) |
等宽且带中文的字体,如更纱黑体 Sarasa Mono SC |
中英文对齐,表格类输出不错位;默认是 Cascadia Mono |
Windows Terminal 回滚行数(historySize) |
50000 |
默认 9001 行,长日志能往上翻得更远 |
PowerShell 历史条数(Set-PSReadLineOption -MaximumHistoryCount) |
10000 |
Ctrl+R 能搜到更早的命令 |
bash 历史条数(HISTSIZE、HISTFILESIZE) |
10000、20000 |
同上 |
PowerShell 输出编码([Console]::OutputEncoding) |
UTF-8 | 外部程序输出的中文不乱码 |
| 提示符 | Oh My Posh 或 Starship | 提示符里显示当前 Git 分支、Python 虚拟环境;两者都支持 PowerShell、bash 和 zsh |
Windows Terminal 的字体和回滚行数写在 settings.json 的 profiles → defaults 里,对所有配置文件生效,设置界面里是“配置文件”→“默认值”;defaultProfile 在 settings.json 的最外层,界面里在“启动”下改,见 4.4。
PowerShell 最小配置,写进 $PROFILE:
[Console]::OutputEncoding = [Text.Encoding]::UTF8 # 外部程序输出的中文按 UTF-8 显示$env:PATH += ";$HOME\tools" # 把自己的工具目录加到 PATH 末尾Set-Alias -Name g -Value git # 简单别名:只换名字,不能带参数function gs { git status -s @args } # 带参数的"别名"写成函数Set-PSReadLineOption -MaximumHistoryCount 10000 # 多存一些历史命令bash 最小配置,写进 ~/.bashrc(macOS 的 zsh 写进 ~/.zshrc,LANG 那行改成 export LANG=en_US.UTF-8,最后三行改成 HISTSIZE=10000 和 SAVEHIST=20000):
export PATH="$HOME/.local/bin:$PATH" # 把自己的工具目录加到 PATH 最前面export LANG=C.UTF-8 # 终端和命令输出用 UTF-8alias ll='ls -la' # 列出全部文件alias gs='git status -s' # 简短的 Git 状态HISTSIZE=10000 # 当前会话记住的历史条数HISTFILESIZE=20000 # 历史文件里保存的条数HISTCONTROL=ignoredups # 连续重复的命令只记一次4.6 注意事项
Section titled “4.6 注意事项”- 运行脚本报“无法加载文件 …,因为在此系统上禁止运行脚本”。 原因:执行策略不允许运行脚本;PowerShell 7 的原文是“因为此系统上已禁用脚本运行”。处理:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser,详见第 1 章。 - PowerShell 里程序输出的中文变成“涓枃杈撳嚭”这样的乱码。 原因:控制台按 GBK 解码,程序输出的是 UTF-8。处理:运行
[Console]::OutputEncoding = [Text.Encoding]::UTF8,写进$PROFILE长期生效,见 4.5。 - 照教程运行
curl -I <url>,报“无法处理命令,因为一个或多个强制参数丢失: Uri。“或停下来让你输入 Uri。 原因:Windows PowerShell 5.1 里curl是Invoke-WebRequest的别名。处理:写成curl.exe,或改用 PowerShell 7。 rm -rf <目录>报“找不到与参数名称 ‘rf’ 匹配的参数。” 原因:PowerShell 的rm是Remove-Item的别名,参数不能合写。处理:Remove-Item -Recurse -Force <目录>;ls -la同理改成Get-ChildItem -Force。- 刚装的工具报“术语 ‘…’ 不会被识别为 cmdlet、函数、脚本文件或可执行程序的名称”或
command not found。 原因:终端只在启动时读一次 PATH。处理:关掉终端重开,VS Code 要整个窗口重开。 - WSL 里
npm install、git status慢得离谱。 原因:项目在/mnt/c/...下,Linux 跨系统读 Windows 的文件很慢。处理:把项目移到 Linux 家目录,如~/projects,再用code .打开。 - 脚本在 Linux 上报
$'\r': command not found或cannot execute: required file not found。 原因:脚本是 CRLF 换行。处理:sed -i 's/\r$//' <脚本>;根治见第 7 章.gitattributes。 - 路径带空格时,
cd my dir报“找不到接受自变量 ‘dir’ 的位置参数。“或cd: too many arguments。 原因:Shell 按空格把路径拆成了两个参数。处理:整个路径加引号,如cd "my dir";用Tab补全路径时,Shell 会自动处理空格。
4.7 深入阅读
Section titled “4.7 深入阅读”- Windows Terminal 文档:安装、设置界面、配置文件、窗格和快捷键的官方说明。
- PowerShell 文档:PowerShell 7 的安装、配置文件、执行策略和全部 cmdlet 参考。
- WSL 文档:安装 WSL、设置 Linux 用户、跨文件系统工作和 VS Code 配合。
- Bash 参考手册:GNU 官方手册,重定向、变量、启动文件的准确规则都在这里。
- ExplainShell:粘贴一条 bash 命令,逐段解释每个部分和参数的含义。