简介:这份面向 macOS 开发者的 Visual Studio Code 通用版压缩包,兼容 Intel 与 Apple Silicon(M1 及后续芯片)两类架构,适合需要快速搭建轻量级代码编辑环境的学生、开发者与运维人员。压缩包共 1167 个文件,整体约 198.27MB,以 JSON 配置与清单、JS/TypeScript 脚本及类型定义、SVG/PNG/ICNS 图标资源、Markdown 说明文档、PAK 与 ASAR 应用资源为主,同时包含多架构原生二进制和 Electron 运行时组件,构成完整的应用目录,便于获得可直接运行的应用包而非零散源码。内容层面,它覆盖语法高亮、IntelliSense 智能补全、多语言调试、内置 Git 版本管理与终端等核心能力;目录中还能看到 TypeScript 代码片段、主题与界面资源、扩展清单及帮助文档,可辅助理解 VS Code 的组成结构并进行个性化配置。已有 174 人学习关注,适合作为 macOS 下日常编码、前端与脚本开发、多语言项目调试的基础工具包。对希望离线保存安装介质、快速恢复编辑器环境或在多台 Mac 上统一配置的读者较友好,也能为研究应用打包结构提供参考。
1. 一个 zip 包和一台 M 芯片的机器:为什么双击解压这一步最容易翻车
有人把一个 VSCode-darwin-universal-1.zip 发过来,说"你直接解压拖进应用程序就行"。听着像最简单的一步,实际上整条安装链路的坑几乎全埋在这里:解压工具不对,.app 的签名封条就散了;没清隔离属性,双击弹"已损坏,应移到废纸篓";包选错架构,Intel 机器上打开就闪退,M 芯片上装成 x64 版本则每次都多绕一层转译。更隐蔽的是装完之后——终端里code找不到、集成终端读不到你的 PATH、便携模式把你原有的扩展全吞了。
这篇记录按"先对表选包 → 解压落位 → 配命令和 PATH → 踩坑回滚 → 装完自检"走一遍,环境是 macOS,覆盖 Intel 和 Apple Silicon 两类机器。如果你手上正好是这个 zip,或者正准备给团队统一发一份 VS Code 安装包,照着往下做一遍就行。
2. 选包对表:universal、arm64、x64 三个包差在哪
macOS 侧的 VS Code 发行包一般有三个:VSCode-darwin-universal、VSCode-darwin-arm64、VSCode-darwin-x64,另外还有.dmg的安装器版本。手里这个是 universal 的 zip,意思是它把两套架构打进同一个 Mach-O 里,一台机器上装一次,Intel 和 Apple Silicon 都能跑。这看起来最省事,但省的事和背的代价是同一件事,先花三分钟对上表,比装完再返工划算得多。
2.1 一条 uname -m 先定架构,但别全信它
很多人拿到包的第一反应是敲uname -m,看到输出就下单。问题是这个命令有个经典的误导:如果你的终端本身是跑在 Rosetta 转译下的(比如从旧机器整机迁移过来,或者终端被设置成"使用 Rosetta 打开"),uname -m会老老实实告诉你x86_64,可机器其实是 M 系列。照着这个结果去下 x64 包,装完能跑,但每次启动都多一层转译,扩展里带原生模块的还容易装不上。
我一般会三条命令一起看,交叉验证:
# 1) 系统版本:决定你能不能装当前发布版本,老系统要往回找旧版本 sw_vers # 2) 机器真实架构:arm64 是 M 系列,x86_64 是 Intel uname -m # 3) 最关键的一条:判断当前进程是不是被 Rosetta 转译过 # 输出 1 表示"你看到的 x86_64 是假的",输出 0 或没有这个键说明是原生 sysctl -n sysctl.proc_translated 2>/dev/null || echo "native-or-no-key" # 4) 兜底:直接问硬件 system_profiler SPHardwareDataType | grep -E "Chip|Processor Name"逐条说一下。sw_vers给的是ProductVersion,比如 12.x、13.x、14.x,VS Code 近两年的版本对最低系统版本有要求,老机器上装不上新版不是包坏了,是系统太旧,得往回找能装的历史版本,这一点在下载页的 System Requirements 里写得很清楚。uname -m是内核报的架构,绝大多数情况可信。第三条是解药:sysctl.proc_translated为 1,说明当前 shell 是被 Rosetta 拉起来的,你看到的x86_64只是转译层的伪装。这时候换成原生终端(或者arch -arm64 zsh起一个),再敲一次uname -m,才是机器的真实架构。
提示:
sysctl.proc_translated这个键在纯 Intel 机器上不存在,命令会报错退出,所以后面接了|| echo。别看到报错就以为环境有问题。
2.2 universal 包的体积账:什么时候值得背
Mach-O 的"胖二进制"(fat binary)是把多份架构的机器码拼在一个文件里,启动时由系统挑对应的那份加载。代价很直接:文件体积约等于两个单架构版本之和。解压出来的 .app 会明显更大,首次启动时系统的签名校验也要多走一遍,后续版本更新下载的包同样是双份。
我的取舍标准大概是这样的:
| 包 | 适用机器 | 体积(相对) | 我什么时候选它 |
|---|---|---|---|
VSCode-darwin-universal-1.zip | Intel + Apple Silicon 都能跑 | 约等于两个单架构之和 | 一份包要发给多人、或不确定目标机器型号 |
VSCode-darwin-arm64.zip | M 系列 | 最小 | 自己用,且确认是 M 机器 |
VSCode-darwin-x64.zip | Intel | 中等 | 自己用,且确认是 Intel 机器 |
表里的包名按 macOS 发行包的常见命名习惯写,具体以你手上压缩包的实际文件名为准,别照抄。
还有一层要考虑的是原生模块。VS Code 本体还好,真正容易翻车的是扩展:调试器、语言服务器、需要本地编译的扩展,里面往往带.node的原生二进制。用 universal 包时,VS Code 会按当前进程的架构去加载对应的 slice,一般不用你操心;而如果你在 M 机器上跑的是 x64 包,进程就是 x86_64 的,扩展也会去找 x64 的原生模块,某些扩展这时候就会报"找不到匹配的二进制"。这也是我给别人发安装包时一律给 universal 的原因——不是它更快,是它把"猜错架构"这个变量消掉了。
2.3 装之前的三项硬检查
选完包别急着解压,先在目标机器上过一遍环境和残留检查。三项:系统版本、磁盘空间、有没有旧版本或旧数据。前两项不满足会很直观地失败,第三项不满足则是"装完看着正常,用起来处处别扭"的那种隐性故障。
| 检查项 | 命令 | 合格线 | 不合格怎么办 |
|---|---|---|---|
| 系统版本 | sw_vers | 不低于下载页标的最低版本 | 往回找历史版本,别硬装 |
| 磁盘空间 | df -h / | 剩余 5 GB 以上比较从容 | 清缓存;扩展多的留更多 |
| 旧版本残留 | ls -d /Applications/*.app | 同名的 .app 只留一个 | 先备份用户数据再删 |
| 用户数据目录 | ls -d ~/Library/Application\ Support/Code | 存在说明是覆盖升级 | 先备份User子目录 |
落到命令上是这样:
# 根分区剩余空间,看 Avail 那一列 df -h / # 列出 /Applications 下所有 .app,肉眼筛有没有 VS Code 的旧版本或改过名的副本 ls -d /Applications/*.app 2>/dev/null | grep -i "visual studio code\|vscode" # 用户配置目录,存在就说明这台机器以前装过 ls -d "$HOME/Library/Application Support/Code" 2>/dev/null && \ ls "$HOME/Library/Application Support/Code/User" # 扩展目录,和上面配套 ls -d "$HOME/.vscode/extensions" 2>/dev/nulldf -h /看的是根分区,Avail那一列是可用空间。为什么建议留 5 GB:.app 本体之外,扩展目录会随使用慢慢长大,调试器、语言包、容器相关扩展都是几百兆起步,再加上工作区的索引缓存,空间紧的机器上容易出现"保存时突然失败"这种莫名其妙的现象。
第二条命令里那个grep -i是有意放宽的,因为很多人会把旧版本改名成Visual Studio Code 1.app之类的留着对比,ls一下就知道要不要先清。第三条和第四条是配套的:用户数据目录存在,说明这不是全新安装,后面第 3 章覆盖 .app 之前得先备份User子目录,否则一不小心就把 keybindings 和 settings 冲掉了。
3. 解压与落位:用 ditto 把 .app 稳稳放进 /Applications
到这一步包已经选好了,接下来是纯手艺活:怎么解、解到哪、怎么放。这一章的三条命令看起来平平无奇,但"应用已损坏"这个报错有八成出在这里,值得慢一点。
3.1 别用 unzip,用 ditto 解 .app
macOS 的.app本质上是个目录,里面除了二进制还有大量符号链接(Frameworks 里那套Versions/Current的结构)和扩展属性。普通的unzip对符号链接和扩展属性的处理是不完整的,解出来的东西可能看起来能用,但内层链接变成了实体文件、或者属性丢了,codesign一验就是"资源被修改过"。系统这时候不会告诉你"解压工具不对",它只会弹一句"已损坏"。
ditto是系统自带的、专门用来做"原样复制"的工具,解压 zip 时会完整保留符号链接、资源叉和扩展属性,这也是 Finder 里双击 zip 走归档实用工具时底层用的东西。
cd ~/Downloads # 先建一个中转目录,别直接在 Downloads 里就地解压 mkdir -p ~/vscode-stage # -x 表示解压,-k 表示源文件是 PKZip 格式 # 目标目录写成已存在的目录,ditto 会把内容解到里面 ditto -x -k "VSCode-darwin-universal-1.zip" ~/vscode-stage # 确认解出来的是 .app,而不是套了一层的文件夹 ls -la ~/vscode-stage参数就三个要知道:-x是解压方向,-k指定源为 PKZip 归档(zip 就是这一类),后面两个位置参数分别是源归档和目标目录。目标目录必须已经存在,先mkdir -p一下,别指望 ditto 帮你建。解完之后ls一下,正常情况下能看到Visual Studio Code.app这一个条目;如果看到的是一个和外层同名的文件夹、里面再套 .app,说明这个 zip 是"多包了一层"的打包方式,后面拷贝的时候路径要相应往里走一层。
注意:Finder 双击解压是可以的,它底层也是 ditto。真正容易出事的是各种第三方解压工具,尤其是默认"智能解压""修复编码"那些选项的。别人发给你的包如果是这么解出来的,别往下走,删掉重解。
3.2 落位 /Applications:先备份,再覆盖
解压出来的 .app 放在~/Downloads或中转目录里也能双击运行,但会有两个后果:一是 Spotlight 索引不到,open -a找不到;二是 macOS 的某些权限(比如完全磁盘访问、屏幕录制)是按路径授权的,挪一次位置就得重新授一次。所以正经做法还是放进/Applications。
覆盖升级的场景要格外小心,顺序错一步就得重来:
APP="/Applications/Visual Studio Code.app" STAGE="$HOME/vscode-stage/Visual Studio Code.app" # 1) 覆盖前先备份用户数据,这两份是真正值钱的东西 mkdir -p "$HOME/vscode-backup/$(date +%Y%m%d)" cp -R "$HOME/Library/Application Support/Code/User" \ "$HOME/vscode-backup/$(date +%Y%m%d)/User" 2>/dev/null # 2) 旧 .app 留一份可回滚的副本,用 ditto 而不是 mv [ -d "$APP" ] && sudo ditto "$APP" "$HOME/vscode-backup/$(date +%Y%m%d)/Visual Studio Code.app" # 3) 用 ditto 覆盖式拷贝,保留签名和扩展属性 sudo ditto "$STAGE" "$APP" # 4) 修正属主,从别人机器或共享盘拷来的包属主可能不对 sudo chown -R "$(id -un):staff" "$APP" # 5) 清掉中转目录,避免下次误用旧包 rm -rf "$HOME/vscode-stage"每一步的意图说清楚。第 1 步备份User目录,是因为settings.json、keybindings.json、代码片段都在这儿,这些是几个月攒下来的东西,丢了没法从安装包恢复。第 2 步用ditto做备份而不是mv,是因为mv跨卷本质是拷贝,中途中断会留下半个包,而ditto失败时至少源还在。第 3 步用ditto而不是cp -R:cp -R对符号链接的处理是"跟随"还是"复制"取决于参数,默认行为在 .app 上容易把内层链接拍平成实体文件,签名就又散了。第 4 步的chown是很多人漏掉的——如果你是从同事的共享盘或者 U 盘里拿的包,里面的文件属主可能是别的 uid,虽然一般不影响启动,但后续更新时会因为写权限失败而报一些看不懂的错。
提示:已经装了一份、只是想升级的,先退出所有 VS Code 窗口再覆盖。进程还在跑的时候覆盖 .app,容易出现"新二进制旧资源"的混合状态,表现是界面能开但某些功能点了没反应。
3.3 Gatekeeper 三道关:隔离、签名、公证
从浏览器或聊天工具下载的文件,macOS 会打上一个隔离属性(quarantine)。这个属性的本意是"这文件来自网络,首次打开前先问一下用户",但它和签名校验叠在一起时,报错信息就会变得很吓人:不是"这是下载的文件",而是"已损坏,无法打开,您应该将它移到废纸篓"。
先看有没有:
APP="/Applications/Visual Studio Code.app" # 列出扩展属性,有 com.apple.quarantine 就是被隔离了 xattr -l "$APP"清掉它:
# -d 删除属性,-r 递归处理 .app 内部所有文件 sudo xattr -dr com.apple.quarantine "$APP" # 再确认一次,应该没有任何输出 xattr -l "$APP" | grep -i quarantine-d是 delete,-r是递归。为什么不加-r不行:隔离属性会被打到 .app 内部的每个文件上,只清最外层那个目录没用,里面那一堆 Frameworks 还是会拦住启动。
清完隔离属性再去双击。近几年的 macOS 版本在这块收紧过:以前"右键 → 打开"能绕过一次,现在更多时候要把应用拖进应用程序文件夹后,去"系统设置 → 隐私与安全性"里找那条被拦截的提示,点"仍要打开",再确认一次。这个过程只需要走一次,之后正常双击就行。
注意:
xattr -dr com.apple.quarantine是给"你确认来源可信"的包用的。如果这个 zip 来路不明,不要养成先清属性再看的习惯,那等于把这道门拆了。
3.4 校验三连:lipo、codesign、spctl
前面几步做对了,这三条命令的输出会非常干净;做错了,它们会直接告诉你错在哪,比反复双击试错快得多。
APP="/Applications/Visual Studio Code.app" # 1) 架构:universal 包应该同时列出 x86_64 和 arm64 lipo -archs "$APP/Contents/MacOS/Electron" # 2) 签名:看 Identifier、Authority 链和 TeamIdentifier 在不在 codesign -dv --verbose=2 "$APP" 2>&1 | head -n 12 # 3) 门禁:结尾是 accepted 才算真正通过 spctl -a -vvv -t execute "$APP" 2>&1第一条,lipo -archs直接读出这个可执行文件里打包了哪些架构。universal 包应该输出x86_64 arm64(顺序可能不同);只有arm64说明你手上是 arm64 包,只有x86_64说明是 x64 包。这条命令是判断"包选错没有"最快的方式,比看文件名可靠——文件名是可以改的。
第二条,codesign -dv里的-d是 display,只展示签名信息不做校验。看两样东西:Identifier是不是正常的应用标识,Authority链有没有列出来。如果这里直接报code object is not signed at all,说明解压过程把签名文件搞丢了,回 3.1 用ditto重来一遍。想更严格可以加--verify --deep --strict,但那会连内层的所有框架一起验,输出很长,日常排查用-dv够了。
第三条,spctl是系统门禁的评估器,-a是 assess,-t execute指定按可执行文件来评估。输出里accepted加上source=Notarized Developer ID是最理想的结果。如果显示rejected,先确认隔离属性已经清干净了,还不行就去系统设置里手动放行一次。
4. 配 code 命令与 PATH:让终端和 VS Code 互相认得
.app 进了/Applications只说明它能双击打开,离"能干活"还差一层:终端里的code命令、集成终端里的环境变量、扩展和配置存在哪。这一层不出问题则已,出问题就是那种"重启一下又好了"的玄学,值得一次配清楚。
4.1 code 命令的三种来源,选一种别混用
命令行工具code本质上是个壳脚本,真正的入口在.app内部的Contents/Resources/app/bin/code。要让它能在终端里直接敲,常见三条路:
第一条,命令面板里执行 "Install 'code' command in PATH"。它做的事其实就是往/usr/local/bin建一个软链,方便,但你没法在脚本里复现,换台机器还得手动点一遍。
第二条,手动建软链。我基本都走这条,因为可以写进装机脚本,出问题也一眼能看出链到哪了。
# 先确认目标文件存在,路径不对后面全白搭 ls -l "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" # Apple Silicon 上 /usr/local/bin 不一定预置,先确保目录在 sudo mkdir -p /usr/local/bin # -s 建软链,-f 强制覆盖已有的,这样升级完 .app 不用重建软链 sudo ln -sf "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" /usr/local/bin/code # 验证:-a 会列出 PATH 里所有同名命令,避免有别的 code 抢先 which -a code code --versionln -sf里的-f值得说一下。它的作用是"目标已存在就覆盖",看着像个危险参数,其实在这里是保险:以后你把旧版 .app 删了重装,软链指向的路径没变,不需要重建;如果不用-f,第二次执行会报 "File exists",然后你就得先rm再建,多一步还容易忘。
which -a是这条链上最有用的一条命令。装了 Homebrew 的机器上,/opt/homebrew/bin往往排在/usr/local/bin前面,如果那里恰好也有个code(某些工具链会带),你敲的code和你以为的不是同一个。-a会把 PATH 里所有匹配项按顺序列出来,第一个就是实际生效的那个。
第三条,用 alias 硬指。alias code="/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"看着也行,但 alias 只在交互式 shell 里展开,任何脚本、任何非交互场景都不认。装完自己用没问题,一旦写进构建脚本就是"我这能跑你那跑不了"。
4.2 PATH 写 .zprofile 还是 .zshrc
macOS 现在默认是 zsh,它有两套启动文件:.zprofile在登录 shell 启动时读一次,.zshrc在每次交互式 shell 启动时读。从 Dock、Spotlight 启动的图形界面程序不经过 shell,所以它读不到.zshrc里的任何东西;而你在终端里敲code .启动 VS Code 时,VS Code 继承的是当前 shell 的环境,集成终端再继承 VS Code 的环境——这条链上只要有一环没读到你的 PATH,集成终端里就会出现"外部终端有 node,集成终端没有"的经典现象。
我的分法是:环境变量一律放.zprofile,交互配置放.zshrc。
# ~/.zprofile —— 只放环境变量,登录时执行一次 export PATH="/usr/local/bin:$PATH" export PATH="$HOME/.local/bin:$PATH" # ~/.zshrc —— 放别名、补全、提示符这类交互配置 alias vsc="open -a 'Visual Studio Code'" # 改完不要在当前窗口自欺欺人,开一个全新的登录 shell 验证 zsh -lic 'echo $PATH'为什么不把export PATH写进.zshrc:每开一个子 shell 就执行一次,PATH 被反复追加,越滚越长;更麻烦的是从图形界面启动的程序根本不读它,于是你会得到"有时生效有时不生效"的错觉。zsh -lic里的-l是模拟登录 shell、-i是交互式、-c是执行后面的命令,这三者组合起来才等价于"新开一个终端窗口",是验证 PATH 改对没有的标准姿势。
4.3 便携模式:data 目录这个黑匣子
zip 版有一个.dmg安装版没有的能力:便携模式。规则很简单——如果.app内部存在Contents/Resources/app/data这个目录,VS Code 会把本该放在~/Library/Application Support/Code和~/.vscode/extensions的东西全部塞进这个 data 目录里。
APP="/Applications/Visual Studio Code.app" # 建 data 目录即开启便携模式 mkdir -p "$APP/Contents/Resources/app/data" # 验证:建完之后这两个路径应该出现 ls -d "$APP/Contents/Resources/app/data/extensions" 2>/dev/null ls -d "$APP/Contents/Resources/app/data/user-data" 2>/dev/null好处很实在:整个 .app 变成一个自包含的盒子,拷到 U 盘、拷到另一台同架构的机器上,配置和扩展全跟着走,不污染宿主机的用户目录。
代价也得说清楚,不然就是个血泪坑。第一,往已签名的 bundle 里塞文件会破坏签名封条,某些系统版本上第二次启动可能被门禁拦下来,弹的还是一句不知所云的验证失败。第二,升级的时候你是覆盖整个 .app 的,data 目录跟着一起没,等于每次升级都要先手动把 data 拷出来再拷回去。第三,扩展里如果有写死绝对路径的配置,路径从~/.vscode/extensions变成 app 内部那一长串,个别扩展会找不到自己的资源。
我的做法是别拿/Applications里那个开刀。要便携,就把 .app 复制到~/Apps或移动硬盘上,在副本里建 data,/Applications里留一个干净的常规安装自用。这样两套互不干扰,也不至于某天门禁翻脸把主力环境锁死。
# 便携式部署:副本放家目录,不动 /Applications 里那个 mkdir -p "$HOME/Apps" sudo ditto "/Applications/Visual Studio Code.app" "$HOME/Apps/Visual Studio Code.app" sudo chown -R "$(id -un):staff" "$HOME/Apps/Visual Studio Code.app" mkdir -p "$HOME/Apps/Visual Studio Code.app/Contents/Resources/app/data"4.4 扩展清单的导出与回灌
换机器、重建环境的时候,真正需要带走的东西只有两样:User目录下的配置文件,和一份扩展 ID 清单。扩展本身别拷,重装一遍比拷目录干净得多,也能顺便把版本更新到当前可用的。
# 导出:只记 ID,不记版本,重装时拿当时最新的 code --list-extensions > "$HOME/vscode-extensions.txt" # 回灌:逐个安装,--force 用于覆盖已存在的同名扩展 while read -r ext; do [ -n "$ext" ] && code --install-extension "$ext" --force done < "$HOME/vscode-extensions.txt" # 校验:对比两边的数量,差一两个就说明有装失败的 code --list-extensions --show-versions | wc -l--force的作用是"已装也重装一遍",批量回灌时很有用,因为它会把那些因为版本冲突卡住的扩展重新拉一次;代价是慢。--show-versions加上去之后能看到每个扩展的版本号,方便和旧机器对比,某些扩展的新版本有破坏性变更时,这一步能提前发现。
配置文件就两份值得备份:~/Library/Application Support/Code/User/settings.json和同目录下的keybindings.json。其余的缓存、日志、工作区状态都别搬,搬过去反而容易出怪问题。
5. 避坑记录:五个报错、它们的原因和我的处理顺序
这一节是按我自己的排查顺序整理的,从"根本打不开"到"能开但用着别扭"排。遇到问题别从头试,先看现象属于哪一类。
5.1 启动类:打不开、已损坏、闪退
坑一:双击弹"已损坏,无法打开,您应该将它移到废纸篓"。
现象很唬人,像是包被传坏了。实际原因九成是隔离属性和签名封条对不上:zip 解压工具把 .app 内部的符号链接或扩展属性搞坏了,codesign在启动前校验时发现"资源被修改",系统就把错误统一翻译成了这句话。
解决办法按顺序来:先xattr -dr com.apple.quarantine清隔离属性;还弹就回 3.1 用ditto重新解压,别用第三方解压工具;再不行跑一次codesign -dv --verbose=2,看是不是真的"not signed at all"。如果是,那这个包在传输过程中已经被破坏了,重新拿一份,别修。
坑二:图标弹一下就没,或者启动后立刻退出,日志里什么都没有。
先在命令行直接跑二进制,把 GUI 层藏起来的错误逼出来:
# 直接执行主二进制,报错会打到 stdout/stderr "/Applications/Visual Studio Code.app/Contents/MacOS/Electron" --version # 如果输出 Bad CPU type in executable,就是架构不对 # 如果提示需要 Rosetta,在 M 机器上装一次 softwareupdate --install-rosetta --agree-to-license看到Bad CPU type in executable,说明在 Intel 机器上装了 arm64 包,或者反过来。这种情况不用修,回第 2 章重新选包。另一种情况是 M 机器上跑 x64 包但系统没装 Rosetta,命令会明确提示,装一次就行。这两类问题用 GUI 完全看不出来,只能靠命令行。
5.2 终端与 PATH 类
坑三:终端里code: command not found,但在命令面板里点过"安装 code 命令"。
原因是命令面板那个操作默认往/usr/local/bin建软链,而这个目录在 Apple Silicon 的机器上不一定存在,或者存在但不在你的 PATH 里。点了没反应,往往是因为它建链失败但提示一闪而过。
解决就是手动来一遍,先确认目录在、再建链、最后用which -a确认生效的是哪一个,命令见 4.1。顺手检查一下echo $PATH,把/usr/local/bin的位置和预期对一下。
坑四:集成终端里node、npm、python全找不到,外部终端一切正常。
这条是我见过最多的玄学。原因在于启动方式:从 Dock 或 Spotlight 启动的图形程序不经过 shell,不读.zshrc,它继承的是登录环境;你把这些工具加进 PATH 的语句如果写在.zshrc里,GUI 启动的 VS Code 就完全看不到。集成终端是 VS Code 的子进程,继承的是 VS Code 的环境,于是也就看不到。
处理办法有两个,我一般两个都用:把 PATH 相关的export全部挪到.zprofile(见 4.2);日常养成从终端code .启动的习惯,这样 VS Code 直接继承了当前 shell 的完整环境,最不容易出问题。改完之后zsh -lic 'echo $PATH'验证一次,别在当前窗口看。
5.3 数据与版本类
坑五:装了两个版本,扩展和设置时有时无,命令行敲的code和双击打开的不是同一个。
现象很有迷惑性:明明刚装的扩展,打开另一个窗口就没了;code --list-extensions列出来的和界面上看到的对不上。原因是/Applications里同时存在Visual Studio Code.app和一个改过名的副本,两者共用同一套用户数据目录,但启动时 LaunchServices 挑哪个是不确定的,加上命令行软链指向的是其中一个,就出现了"两个世界"。
先查清楚现状:
# 看 code 命令实际指向哪个 .app readlink -f "$(which code)" # 找出磁盘上所有同名 .app(包括家目录、下载目录里的副本) mdfind -name "Visual Studio Code.app" # 列出 /Applications 下所有可能的重名副本 ls -d /Applications/*.app | grep -i "visual studio\|vscode"处理原则是"只留一个真正干活的"。留/Applications里那个作为日常使用,其余副本要么删掉,要么改成便携模式并明确知道它用的是自己 data 目录里的那套配置(见 4.3)。如果删完还是不对劲,刷一次 LaunchServices 的注册缓存:
# 重建 LaunchServices 数据库,让系统重新扫一遍应用注册信息 /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister \ -kill -r -domain local -domain system -domain user这条命令跑完要几秒到几十秒,期间别做别的操作。它的作用是清掉系统对 .app 的旧索引,"双击打开的是另一个版本"这类问题大多能解决。
6. 装完怎么验证:五分钟自检清单
装完之后我不太相信"能打开就算成功",因为很多问题是延迟暴露的:今天能开,明天装个带原生模块的扩展才发现架构不对;今天code能用,重启一次 shell 才发现 PATH 写错了地方。所以我固定跑一遍自检,把该暴露的问题一次暴露出来。
| 检查项 | 正常输出 | 异常时先看这里 |
|---|---|---|
| 系统版本 | sw_vers不低于最低要求 | 回 2.3,考虑退版本 |
| 应用版本 | CFBundleShortVersionString有值 | 包不完整,重新解压 |
| 架构 | lipo -archs两个架构都在 | 回第 2 章重新选包 |
| 签名 | codesign -dv有 Authority 链 | 回 3.1 用 ditto 重解 |
| 门禁 | spctl结尾是 accepted | 清隔离属性、手动放行 |
| 命令 | which -a code只有一条或第一条正确 | 回 4.1 重建软链 |
| 数据目录 | 只出现一套(用户目录或 data 二选一) | 回 4.3 确认便携模式 |
把上面这些串成一个脚本,以后每装一台机器跑一次:
#!/usr/bin/env bash # vscode-check.sh —— 装完先跑这个,任何一项异常都别急着装扩展 APP="/Applications/Visual Studio Code.app" echo "== 1. 系统 ==" ; sw_vers ; uname -m echo "== 2. 应用版本 ==" ; defaults read "$APP/Contents/Info.plist" CFBundleShortVersionString echo " <p> <a href="https://download.csdn.net/download/m0_75083264/86945439" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>