news 2026/9/30 12:00:05

彻底卸载Node、npm与Homebrew:macOS与Windows残留清理完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
彻底卸载Node、npm与Homebrew:macOS与Windows残留清理完整指南

先说个真实经历。有段时间我的 Mac 上node -v和npm -v永远对不上,brew 每次升级都能带出新的报错,Angular 9 的项目要求 node 12,另一个仓库又非要 18 起步。忍了好几周之后我做了个决定:把 node、npm、homebrew 全部卸掉,从零建一套干净环境。事后回头看,那次卸载比我预期的麻烦得多——原因很简单,这三个工具在系统里留下的痕迹远不止一个命令文件。

这篇文章就是那套完整卸载流程的记录。macOS 和 Windows 都会讲到,包含 Homebrew 的官方卸载脚本、残留目录清理、node/npm 的多种安装路径对应清理方式,以及很多人在 Windows 上遇到的npm.ps1无法加载、被禁止运行脚本的问题。适合三类人:想彻底清掉旧环境重来的、被 PATH 和残留配置折磨的、以及刚接触这些工具想先搞清楚卸载逻辑的新手。

1. 为什么要把 node、npm 和 homebrew 一并清掉

很多人对“卸载”的理解是:删掉可执行文件、删掉主目录,完事。实际这套逻辑用在 node、npm、homebrew 上根本不成立,因为这三个工具的安装过程会在系统里埋下好几层痕迹,缺了哪一层都不算干净。

1.1 只卸一半的尴尬:全局包和残留配置不会自动消失

先说一个最常见的错误操作:brew uninstall node,然后以为 node 没了。但如果你的 node 根本不是用 brew 装的,而是从官网下载 pkg 装的,这个命令卸的只是 brew 自己的 formula 记录,/usr/local/bin/node这个软链反而指向另一个真实的 node 文件,卸载完成后node -v照样有输出。

npm 的全局包也是一样的道理。很多人全局装过@angular/cli、commitlint、corepack之类,这些包默认落在/usr/local/lib/node_modules(Intel 或官方 pkg 场景)。你卸载了 node 本体,这个目录里几十个全局包可能还在,重装完 node 之后它们依然能被 require,但版本和依赖却是旧的,甚至和新的 node 不兼容。

还有隐藏的配置文件。~/.npmrc里可能存着你的 registry 镜像地址、公司私有源、甚至某些登录 token。不删掉的话,重装完 npm 第一次安装包时,它会静默地用旧配置去请求一个已经失效的地址,然后给你报一个莫名其妙的 404。

1.2 真正值得全套清掉的三种场景

不是所有情况都需要走到“卸载三件套”这一步,我总结下来,值得全套清掉的场景基本是这三种:

第一种,版本管理器和包管理器混用。前脚用 nvm 装了 node 16,后脚又用 brew 装了 node 18,两个二进制文件都在 PATH 里,谁的优先级高取决于 shell 配置文件的加载顺序。今天打开终端是 16,明天重启变成了 18,全局包装到哪套环境全看运气。这种混乱靠“卸掉其中一个”很难解决,因为两个安装路径都写进了 PATH,不如全清干净再统一用一套方案。

第二种,homebrew 自己已经坏了。brew update 一直报错、自检不通过、权限错乱,或者网上搜到一堆“homebrew 卸载残留”的帖子,说明它的状态已经不可维护。这时候单独修 brew 的成本往往比重装还高。

第三种,环境要整体交付或长期复用。比如要在 CI 机器、共用开发机上重建一套标准环境,最稳妥的做法不是在新机器上叠加各种补丁,而是先明确“当前机器上没有旧工具干扰”。

1.3 卸载的本质:撤销安装时的所有写入点

我后来给自己总结了一个很直白的定义:卸载 node、npm、homebrew,不是在删软件,而是在撤销当初安装时对系统的所有写入点。

一个工具装进系统,至少会写入这几个地方:可执行文件或软链、包目录、配置目录、缓存目录、shell 启动文件(PATH 配置)。卸载时就要反过来检查这些位置。所以后面两章的清理顺序,也是按照这个思路设计的:先跑官方卸载脚本干掉主要文件,再按路径排查残留目录,最后清理 shell 配置。

2. macOS 端 homebrew 的完整卸载链路:官方脚本加残留战场

macOS 下卸载 homebrew,第一步永远是跑官方卸载脚本,而不是手动rm -rf。但很多人不知道的是,官方脚本跑完之后,系统里其实还留着不少东西。

2.1 先跑官方卸载脚本,看它到底做了什么

Homebrew 官方提供了一站式卸载脚本,官方文档里推荐的方式是运行这条命令:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"

执行之后,脚本会先扫描当前已安装的 formula 和 cask,然后问你几个问题,常见的是这两个:是否确认卸载 Homebrew,以及是否连同它安装过的软件包一起删除。如果你希望环境“彻底干净”,这两处都选 yes;如果你只是想卸掉 brew 本体、但想保留某些用 brew 装过的命令行工具,就选 no,之后自己手动处理。

跑这个脚本之前,强烈建议先做一件事:brew list --formula和brew list --cask,把当前装过的所有包列出来存个档。我有一次卸载前没存档,脚本清理完才发现有个依赖是 brew 装的,后来翻了一下午才找到替代安装方式。

脚本执行时间取决于装机量,一般几分钟到十几分钟不等。期间它会打印删除路径的日志,建议截图或保留输出,后面排查残留时能省不少事。

2.2 脚本不会帮你清的目录:按芯片平台分情况处理

官方脚本卸载的是“Homebrew 自己认知范围内的文件”,但它对系统目录里的一些散落文件夹并不总是完全清理。这也是“homebrew 卸载残留”问题的主要来源。

Apple Silicon(M 系列芯片)的 Mac,brew 主目录是/opt/homebrew,卸载脚本正常情况下会把整个目录干掉。但如果你之前往里面手动放过东西,或者某些进程还在占用,脚本可能只删了它管理的一部分,剩下一个空壳目录。Intel 芯片的 Mac 更麻烦,brew 的文件分散在/usr/local下的很多子目录里。

下面这张表是按常见残留位置整理的,建议逐个检查:

路径作用是否常见残留
/opt/homebrewApple Silicon 下 brew 主目录是
/usr/local/HomebrewIntel 下 brew 程序目录是
/usr/local/CellarIntel 下已安装 formula 的实体目录是
/usr/local/Caskroomcask 应用的安装目录常见
/usr/local/Frameworks部分依赖的 framework偶尔
/Library/Homebrew系统级共享目录较少
~/Library/Caches/Homebrew下载缓存非常常见
~/Library/Logs/Homebrew日志常见

确认脚本已经把该删的删了之后,再手动补刀:

# Apple Silicon 用户 sudo rm -rf /opt/homebrew # Intel 用户 sudo rm -rf /usr/local/Homebrew /usr/local/Cellar /usr/local/Caskroom /usr/local/Frameworks # 通用:清理用户级缓存和日志 rm -rf ~/Library/Caches/Homebrew rm -rf ~/Library/Logs/Homebrew

这里必须强调一个很多人踩过的坑:Intel 机器上不要直接sudo rm -rf /usr/local。/usr/local下面可能有你自己编译装的其他工具、手动放的脚本、甚至其他包管理器写的文件,整个目录删掉会误伤一片。

2.3 PATH 里的 brew 残留怎么彻底抹掉

brew 安装时会在 shell 启动文件里写入配置,最常见的两行是:

eval "$(/opt/homebrew/bin/brew shellenv)"

正式环境变量或者在/etc/paths.d目录下放一个专门的文件,总之你的PATH里只要还在找 brew,which brew就可能指向一个不存在的路径,进而让终端每次启动都慢半拍、甚至报错。

排查方法很简单:

which -a brew grep -n brew ~/.zshrc ~/.zprofile ~/.bash_profile /etc/paths /etc/paths.d 2>/dev/null

有输出就说明还有残留。个人经验是,最常出问题的是~/.zshrc里的eval那行,删掉即可;/etc/paths.d下如果有 Homebrew 开头的文件,用sudo rm -f删掉。如果你用的是 fish shell,还要检查~/.config/fish/config.fish。

如果你打算之后用其他包管理器(比如后面要提到的 nvm、fnm),这一步反而是检查 PATH 写入逻辑的最好时机——每加一个工具,你就能明确知道它往哪里写了配置。

3. macOS 上 node 和 npm 的清理:先分清是“谁装的”再动手

装过 type-c 充电器的人都知道,同一个接口,不同充电头的协议完全不同。node 和 npm 的安装也是这样——nvm 装的、brew 装的、官方 pkg 装的,路径和卸载方式完全不同。你没法用同一个命令覆盖三种情况,所以第一步永远是确认来源。

3.1 三步确认 node 的来源

开个终端,依次执行:

which node ls -l $(which node) brew list --formula | grep node

结果大概有四种情况:

  • 路径是~/.nvm/versions/node/...,说明 node 是 nvm 管的;
  • 路径是/opt/homebrew/bin/node或/usr/local/bin/node,且brew list里有 node,说明是 brew 装的;
  • 路径是/usr/local/bin/node,但brew list里没有 node,那大概率是官方 pkg 装的;
  • 多个路径同时存在,说明环境已经混了,按下面三种情况分别清。

这里有个容易看走眼的细节:官方 pkg 安装时创建的/usr/local/bin/node是一个软链,指向真实的安装目录(比如/usr/local/nodejs/bin/node)。只看which node可能觉得路径很干净,一定要再看一眼ls -l结果里的->指向。

3.2 分情况清理:nvm、brew、官方 pkg 三种路径

情况 A:nvm 管理。先在 nvm 里把装的版本一个个卸掉:

nvm ls nvm uninstall 16 nvm uninstall 18

然后再把 nvm 本身从系统里移除:

rm -rf ~/.nvm

同时清理 shell 配置里和 nvm 相关的三行样板代码(通常在~/.zshrc或~/.bash_profile里)。这里容易漏的是:nvm 会在~/.npmrc里留下一个prefix配置,指向 nvm 的目录,重装完如果有配置冲突,先回来查这里。

情况 B:brew 装。直接:

brew uninstall --ignore-dependencies node

加--ignore-dependencies是因为有些用户装 node 是作为其他包(比如某些 ruby 工具链)的依赖出现的,默认卸载会连带追问依赖处理,加这个参数可以只卸 node 本体。如果你已经执行过上一章的 brew 卸载脚本,这一步通常可以跳过,brew 脚本会把 node 的软链一起清掉。

情况 C:官方 pkg 装的。先找到包 ID 并注销系统记录:

pkgutil --pkgs | grep node sudo pkgutil --forget org.nodejs.node.pkg

pkgutil --forget只是删除“包安装记录”,不会删文件。所以接下来还要手动删安装时写入的文件:

sudo rm -rf /usr/local/bin/node \ /usr/local/bin/npm \ /usr/local/bin/npx \ /usr/local/bin/corepack \ /usr/local/lib/node_modules \ /usr/local/include/node \ /usr/local/share/doc/node \ /usr/local/share/man/man1/node.1

如果你用ls -l /usr/local/bin/npm看到指向别处,手动顺着软链目标把真实目录也删掉。这一步别怕误删,/usr/local/bin下的 node 系目录基本都是 node 相关,不会碰到其他工具。

3.3 缓存与全局配置:~/.npm、~/.npmrc、~/.node-gyp 别漏

不管 node 是从哪个渠道装的,这最后一项清理必须是同一套:

rm -rf ~/.npm rm -rf ~/.npmrc rm -rf ~/.node-gyp

~/.npm是 npm 的本地缓存目录,长期安装各种包后会积累几个 GB 的压缩文件,卸载后不删,等于白卸;~/.npmrc前面提过,里面可能存了默认 registry、镜像源、登录凭据;~/.node-gyp是编译原生模块时的缓存,里面往往带着旧的 node 头文件,新版本装某些包含 C++ 代码的包时会因为这个目录里的旧头文件编译失败。

如果你在别的目录里还配置过.yarnrc或者 pnpm 的store路径,想彻底的话也顺手处理,但 node 系列的根,还是上面三个。

4. Windows 端 node/npm 卸载与 PowerShell 脚本权限坑

Windows 的卸载流程和 macOS 不同,主要靠 MSI 卸载器外加手动清理。这里最常见的问题是:卸载完 node,却发现 npm 命令还在,或者干脆在卸载前就遇到了npm.ps1被禁止运行的尴尬。

4.1 常规卸载流程:程序和功能、目录、环境变量三件套

如果你是在“设置 → 应用”或“控制面板 → 程序和功能”里看到 Node.js,直接走系统卸载,MSI 卸载器会把C:\Program Files\nodejs(或你当初自定义的路径,比如热搜里常见的D:\Program Files (x86)\nodejs)里的主文件清掉。

但光这一步不够,MSI 卸载器并不会清理全局包和缓存,因为那些目录是在用户主目录下,不在 MSI 的监控范围里。卸载完后需要手动处理这几处:

  • C:\Program Files\nodejs或D:\Program Files (x86)\nodejs——如果卸载器没删干净,手动删;
  • %APPDATA%\npm——全局包目录,里面有node_modules和一堆.cmd脚本;
  • %APPDATA%\npm-cache——npm 缓存目录;
  • %LOCALAPPDATA%\Programs\Nodejs——部分安装包版本的实际安装目录。

然后是环境变量。右键“此电脑 → 属性 → 高级系统设置 → 环境变量”,在用户变量和系统变量的 Path 里,删掉所有包含nodejs、%APPDATA%\npm的条目。

这里有个血泪教训:动手改 Path 之前,先把当前值复制到文本编辑器里存一份。Windows 的编辑器没有 Ctrl+Z,删错了想恢复,只能靠这份备份。另外要注意,有些版本的 npm 会在用户变量 Path 里写入C:\Users\用户名\AppData\Roaming\npm,而不是%APPDATA%\npm,搜路径时两个关键词都要搜。

4.2 全局包与缓存目录:一定要手动补刀

如果你的 npm 还能运行,卸载前先列一下全局包,方便之后重装:

npm ls -g --depth=0

不需要逐条卸载这些包,因为它们会随%APPDATA%\npm整个目录被删掉。真正要确认的是:这个目录本身还残留了什么。我见过的情况是,Node 从 14 升级到 18 之后,%APPDATA%\npm里的旧ng.cmd、nest.cmd还留着,新版的命令行工具装不上,就是因为旧.cmd文件占着路径却指向不存在的旧包。

清理命令就是删除目录,PowerShell 下可以这样:

Remove-Item -Recurse -Force "$env:APPDATA\npm" Remove-Item -Recurse -Force "$env:APPDATA\npm-cache"

顺手检查一下%LOCALAPPDATA%下有没有.npmrc之类的隐藏文件,有就一起删。

4.3 npm.ps1 被禁止运行的根源:PowerShell 执行策略

很多人没卸载前就被这个问题卡住:在 PowerShell 里敲npm,报错内容大致是:

npm : 无法加载文件 D:\Program Files (x86)\nodejs\npm.ps1,因为在此系统上禁止运行脚本。

这个报错的根源和 node 本身没关系,是 PowerShell 的执行策略(ExecutionPolicy)在管。Windows 上的 npm 提供了两个入口:npm.cmd给 cmd 用,npm.ps1给 PowerShell 用。PowerShell 的默认执行策略是 Restricted,意思是任何.ps1脚本都不允许运行。所以,不是 npm 坏了,是 PowerShell 拒了它。

不想动执行策略的话,有两个绕过方式。第一,在 cmd 里运行npm,cmd 会走npm.cmd,完全不受影响;第二,在 PowerShell 里显式调用npm.cmd,比如npm.cmd config list。

如果你希望 PowerShell 里能正常用 npm,最正规的做法是只修改当前用户的执行策略:

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

RemoteSigned的意思是:本地创建的脚本可以运行,从互联网下载的脚本必须带可信签名。这样既解决了 npm.ps1 的问题,又不会把系统执行策略放开到不安全级别。执行完之后可以用Get-ExecutionPolicy -List确认一下各作用域的设置层级。

这里多说一句:网上很多教程让你Set-ExecutionPolicy Unrestricted,其实没必要。为了一个 npm 命令把整个执行策略放开,等于把所有本地脚本都赋予了运行权限,风险不划算。RemoteSigned足够满足日常使用。

如果你是因为打算卸载 node 才遇到这个报错,其实可以跳过它直接走 4.1 的 MSI 卸载流程,并不需要先解决 npm 能不能用。只有当你希望在卸载前备份全局包列表时,才需要先靠上面任一方式把 npm 跑起来。

5. 清完之后怎么装一个“不太容易再坏”的环境

卸载不是最终目的,重装一套清爽的环境才是。这一章分享的安装思路,核心是:别再用“官网下载 pkg + 一路下一步”的方式装 node,也别再裸奔一个 homebrew 不管镜像。这两件事,各自都有可以提前避坑的成熟做法。

5.1 node 环境:用版本管理器,别用官方 pkg 直接上

重装 node 时,强烈建议用版本管理器,macOS 上最常用的是 nvm,Windows 上是 nvm-windows。用版本管理器有几个好处:版本随意切换、按项目独立指定 node 版本、卸载时只要删目录和配置即可,不会再留下 pkg 安装那种遍布系统的软链。

macOS 的 nvm 安装脚本是这样的:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

如果raw.githubusercontent.com访问不稳定导致脚本拉不下来,可以多试几次,或者先把 install.sh 内容保存到本地再bash install.sh,核心是让脚本在你的 shell 配置里写入 nvm 的初始化代码。装完重开终端,然后:

nvm install 18 nvm use 18 nvm ls

Windows 用户则去 nvm-windows 的 release 页面下载安装包,安装前确保旧 node 已经按上一章流程清理干净,否则 nvm 会检测到已有 node 环境并提示你先卸载。

如果对 nvm 的加载速度不满意,mac 上还可以考虑 fnm 或 volta,它们都是 Rust 写的版本管理器,切换速度更快,但基本思路一样。我个人的建议是:在“能切换 node 版本”这个层面,nvm 的资料最多,踩坑方案最好找,新手先选 nvm 最稳。

5.2 npm 镜像源一次配好,不再被网络卡脖子

npm 默认 registry 是官方源,国内访问速度不稳定,装个大型依赖动辄卡十几分钟。镜像源是标准做法,目前最常用的是 npmmirror(原淘宝镜像):

npm config set registry https://registry.npmmirror.com npm config get registry

这里插一句关于.npmrc的建议:镜像源配置会写进~/.npmrc(Windows 是%USERPROFILE%\.npmrc),重装完第一次执行npm config get registry确认输出是你配置的地址,再装包,能省掉很多“下载超时”的排查时间。

如果你在公司环境里有私有源,配置思路也是一样的,只是 registry 地址换成公司源,必要时再配合.npmrc里的@scope:registry做包级路由。

5.3 重装 homebrew 的国内网络姿势

热词里经常看到“mac 安装 homebrew 失败”“国内 mac 安装 homebrew 失败”,核心原因大多是安装脚本和后续下载都依赖访问 GitHub 和 ghcr.io 的存储服务,网络稍不稳定就断在半路。

在确认网络正常情况下,推荐在安装前先设置几个国内镜像环境变量。以清华 TUNA 的 Homebrew 镜像为例,在终端里先执行:

export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api" export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles" export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git" export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git"

然后再执行官方安装脚本:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

建议把这些 export 写入~/.zshrc持久化,否则新终端窗口又丢了。装完后运行brew --version、brew install任一包试试,确认走了镜像源。需要注意:镜像站的路径可能随版本调整,以对应镜像站首页说明为准;另外不同镜像(阿里、中科大、腾讯)给出的变量名和 URL 可能略有差异,选一家即可,别叠加混用。

我还想提一个更省事的思路:如果只是开发 node 项目,不装全局编译型工具,homebrew 其实不是必需品。node 版本管理 + npm 全局包基本覆盖了九成场景。先想清楚是否真的需要一个系统级包管理器,再决定要不要折腾 brew,能省掉很多后续维护成本。

卸载这件事,我最深的体会是:清理的不只是“软件本身”,而是它留在系统里的所有痕迹。每次图省事只跑一条官方卸载命令,过两周大概率会因为某个 PATH 残留回来补课。按本文链路走一遍,大概十来分钟,换来的是一个 node 相关命令完全可控的干净环境。至少对我和我身边的同事来说,这笔时间花得相当值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 11:56:07

SmartBI CLI 上架 WorkBuddy,让企业数据随问随查

AI Agent正在成为新的工作入口。用户在对话中处理文档、搜索信息、调用工具时,也会随时产生数据需求:临时确认一个指标、查一组经营数据,或者进一步了解企业里有哪些数据可以使用。 现在,SmartBI CLI 已正式上架 WorkBuddy。 完成…

作者头像 李华
网站建设 2026/9/30 11:55:29

SpringBoot+Vue社区交流平台:源码解析与部署实战

这两年接到的这类需求特别多:一套基于SpringBoot的社区技术交流平台,带完整源码、部署文档和代码讲解,最好能直接跑起来、能答辩、能写进简历。很多人把源码下载下来就卡住了,要么环境不对启动报错,要么数据库脚本不知…

作者头像 李华
网站建设 2026/9/30 11:55:25

网络规划师考点结构化:场景-标准-命令三维落地法

简介:本资源是面向网络规划师(高级)考试备考者的系统性考点整理资料,由一线考生结合2022—2023年真题动态更新而成,聚焦高频、易错及近年新增技术点,助力考生高效突破知识盲区与理解瓶颈。资料以1个434KB的…

作者头像 李华
网站建设 2026/9/30 11:54:09

Pandas Series 深度实战:从索引对齐到数据清洗的核心技巧

处理数据这几年,Pandas是我每天都会碰的工具,而 Series 就像它手里最不起眼却又最核心的那块积木。很多人一上来就抱着 DataFrame 啃,遇到一堆问题之后才发现,Series 才是真正值得先搞明白的东西——它是 Pandas 轴上的基本单元&a…

作者头像 李华
网站建设 2026/9/30 11:53:29

CentOS7 离线源码编译升级 OpenSSH 9.8:配置迁移与回滚实战

凌晨两点多收到一条漏洞扫描告警,报告里写着某台内网机器的 OpenSSH 版本低于安全基线,存在若干可被远程利用的问题,要求 24 小时内整改。这种事在运维圈太常见了——CentOS7 上跑的服务器,OpenSSH 还是当年装机时系统自带的 7.4p…

作者头像 李华
网站建设 2026/9/30 11:52:37

SAP数据中台与S/4HANA落地:一套可复用的集团数字化转型架构方案

简介:某大型集团数字化转型方案PPT,聚焦大型企业数字化转型的顶层设计与落地实施,适合集团高管、IT架构师及数字化项目团队用于方案规划与内部评审。内容系统覆盖数据中台、业务应用、总体架构与落地路径,并结合SAP Fiori、S/4HAN…

作者头像 李华