我前阵子在一台 Ubuntu 18.04 服务器上部署新项目项目要用到较新特性的 Node.js结果翻开服务器一看默认apt源里的 Node 还停在 8.x 或 10.x。这年头别说跑 Vite 7就是装个像样的现代前端工程化工具链都费劲。折腾了一整天换了三种安装方式总算是把高版本 Node 稳定地跑了起来。这篇文章就把我实际踩过的路完整走一遍为什么 Ubuntu 18 自带 Node 那么旧、有哪几条路可以装高版本、每一步背后的原理是什么、以及最容易让人卡住的那个系统库版本问题。无论你是运维老手还是刚接触 Linux 的开发新手按下面的顺序操作基本都能顺利装好。1. 为什么 Ubuntu 18 自带 Node 版本那么旧1.1 背后的根源apt 源的更新策略很多人上来就执行sudo apt install nodejs装完一看版本就懵了。这不是操作错误而是 Ubuntu 的软件源策略决定的。Ubuntu 18.04 是 2018 年发布的 LTS 版本它的main源里的 Node.js 版本基本固定在发布时的那个大版本上之后只会做安全修复不会主动升级大版本。对系统维护者来说这很稳妥但对开发者来说就非常难受新框架、新工具链普遍要求 Node 16 以上老版本根本跑不动。另外 Ubuntu 仓库里那个nodejs包实际是 Debian 维护的定制版本跟 Node.js 官方发布版本在组织方式上有差异。如果你习惯去官网下载 LTS 版本再用apt装出来的版本作对比你会发现两者并不完全一样。所以不要指望apt源里能直接给你一个 18.x 或 20.x 的“高版本”这是设计如此不是系统坏了。1.2 安装高版本有哪几条路可选在 Ubuntu 18.04 上装高版本 Node主流方案其实是三条路用nvm做多版本管理相当于在用户目录里维护一套独立的 Node 环境不受系统源限制。用NodeSource等第三方源把官方编译好的 Node 包通过apt直接装成系统服务。用官方二进制压缩包手动解压然后把路径指到PATH里最无侵入。三条路我全都实测过各有各的适用场景。如果你想长期在一台机器上切换多个 Node 版本nvm 最舒服如果你要把 Node 当作系统服务来跑并且希望systemd能直接管理NodeSource 源方式最正规如果你只是临时给某个账户准备 Node或者不想动系统目录二进制压缩包最干净。2. 方案一用 nvm 装多版本 Node最省心2.1 nvm 是什么它凭什么能装高版本nvm 的全名是 Node Version Manager它做的事情简单说就是把不同版本的 Node 下载到~/.nvm目录下然后通过修改当前终端会话里的PATH环境变量让你在不同版本之间切换。它不去动/usr/bin/node这种系统目录所以不会跟系统的包管理器产生冲突。它能装高版本的关键原因在于它是直接从 Node 官方服务器拉取编译好的二进制包并不依赖 Ubuntu 18 的软件源。所以即使 Ubuntu 仓库里的 Node 停留在老版本nvm 一样能拿到官方最新发布的 Node 18、Node 20 甚至更高的版本。不过要注意这里有个隐藏的坎nvm 只负责把二进制包拉下来能不能跑起来还要看系统的 glibc 版本够不够。这个问题我在第 5 节专门讲。2.2 实测安装流程脚本、版本选择、环境变量先确保系统里有基础工具没有的话先装一下sudo apt update sudo apt install -y curl wget git build-essential然后执行 nvm 官方安装脚本。这个脚本会在你的用户主目录下创建.nvm文件夹并把环境变量配置写进.bashrccurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash安装完成后新开的终端会自动加载 nvm但如果当前终端还想继续用需要手动重新加载配置export NVM_DIR$HOME/.nvm [ -s $NVM_DIR/nvm.sh ] \. $NVM_DIR/nvm.sh接着就可以安装指定版本的 Nodenvm install 18 nvm use 18 nvm alias default 18这里我建议你先装 Node 18 LTS而不是直接装最新版。原因很简单Ubuntu 18.04 系统的 GLIBC 版本比较旧Node 20 及以上的官方预编译二进制在跑起来的时候可能报版本找不到的错误。Node 18 是官方仍然支持在 Ubuntu 18.04 环境里跑得比较顺的大版本。2.3 常用命令和切换技巧装好之后几个高频命令值得记一下nvm ls # 查看已安装的所有版本 nvm ls-remote # 查看远程所有可安装版本 nvm install 16 # 安装指定大版本的最新版本 nvm current # 查看当前使用的版本 nvm use 18 # 切换当前 shell 的版本 nvm alias default 18 # 设置默认版本新终端自动使用我在实际使用中有一个体会每个项目尽量在项目目录里写一个.nvmrc文件内容就是一行版本号比如18。这样团队成员进到项目目录后执行nvm use就能自动切到项目需要的版本不用每个人记版本号。这个习惯帮我少踩了很多“本地能跑、服务器跑不了”的坑。3. 方案二用 NodeSource 源安装高版本3.1 NodeSource 源的工作原理与适用场景NodeSource 是一个第三方软件源服务商它把 Node.js 官方编译好的包重新打包成 Debian/Ubuntu 的deb格式然后通过apt来安装。这种方式的好处是安装完之后 Node 会被纳入系统的包管理器体系升级、卸载都跟普通系统软件一致systemd之类的服务管理工具也能直接对接。对 Ubuntu 18.04 来说这套方案我印象里比较顺的是装 Node 16 和 Node 18。NodeSource 对老版本系统的支持会逐渐收窄如果你执行后面的命令时发现源里找不到对应版本不要硬刚换回 nvm 方案即可。3.2 一条命令安装并开机自启systemdNodeSource 官方给了一个一键脚本原理是导入 GPG 密钥、配置 apt 源地址、更新索引然后就可以用apt安装了curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt-get install -y nodejs第一行命令执行完系统里已经多了一个/etc/apt/sources.list.d/nodesource.list文件里面指向的就是 NodeSource 的仓库。-E参数是保留你当前用户的环境变量避免代理等设置丢失。装完之后验证node -v npm -v如果你的项目需要开机自启可以顺手创建一个 systemd 服务文件。比如有一个 Node 服务放在/opt/myapp/app.js你就可以这样建服务sudo tee /etc/systemd/system/myapp.service /dev/null EOF [Unit] DescriptionMy Node App Afternetwork.target [Service] ExecStart/usr/bin/node /opt/myapp/app.js Restartalways Userwww-data EnvironmentNODE_ENVproduction [Install] WantedBymulti-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now myapp这样 Node 应用就跟系统服务一样崩溃自动拉起开机自动启动。3.3 升级、卸载等后续维护用 NodeSource 装出来的 Node后续升级直接用系统包管理工具就行sudo apt-get update sudo apt-get upgrade nodejs如果要彻底卸载先移除软件包再清理源文件sudo apt-get remove -y nodejs sudo rm -f /etc/apt/sources.list.d/nodesource.list sudo apt-get update我建议卸载前先看看有没有全局 npm 包还需要留着因为卸载 Node 并不会自动清掉/usr/lib/node_modules里的全局模块下次重装时可能会残留。稳妥做法是先执行npm list -g --depth0把清单导出来。4. 方案三二进制压缩包手动安装最无侵入4.1 为什么某些场景必须用手动安装有些服务器的安全策略不允许添加第三方 apt 源或者你只是想在某个普通用户的目录下放一个独立的 Node不想动系统目录。这种情况下二进制压缩包方案就很有优势。它不需要 root 权限也不写系统级配置完全就是一个“绿色软件”。从 Node 官方下载站选好版本号x64 架构的 Ubuntu 18 服务器一般用linux-x64包。我这边用的是 18.20.4这是 18 系列里一个很稳定的版本wget https://nodejs.org/dist/v18.20.4/node-v18.20.4-linux-x64.tar.xz4.2 以普通用户身份安装的完整操作解压到用户目录然后把可执行文件所在的bin目录加进PATHmkdir -p ~/nodejs tar -xJf node-v18.20.4-linux-x64.tar.xz -C ~/nodejs --strip-components1--strip-components1的作用是去掉压缩包第一层目录名让文件直接解压到~/nodejs下面。接下来配置环境变量。编辑~/.bashrc在末尾追加export PATH$HOME/nodejs/bin:$PATH然后重新加载source ~/.bashrc验证版本node -v npm -v如果你有 root 权限更常见的做法是把解压出来的目录放到/usr/local/然后做软链这样所有用户都能用sudo tar -xJf node-v18.20.4-linux-x64.tar.xz -C /usr/local/lib sudo ln -s /usr/local/lib/node-v18.20.4-linux-x64/bin/node /usr/local/bin/node sudo ln -s /usr/local/lib/node-v18.20.4-linux-x64/bin/npm /usr/local/bin/npm sudo ln -s /usr/local/lib/node-v18.20.4-linux-x64/bin/npx /usr/local/bin/npx普通用的话用户目录方案就够了。但要注意用软链方式装 npm 全局包时可能会遇到 npm 去修改软链指向的原始目录的权限问题需要配合--prefix或者确保目录属主正确。5. 必须提前避开的坑glibc 版本与 Node 版本对应5.1 Ubuntu 18.04 的 glibc 究竟卡住了谁这是我在实际部署中遇到的最隐蔽、最头疼的问题。现象是你明明用 nvm 或二进制包装好了 node执行node -v却报错类似node: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.28 not found (required by node)原因不在 Node 本身而在于预编译二进制包所依赖的系统 C 库版本。Ubuntu 18.04 默认的 glibc 是 2.27而 Node.js 20 及以上版本的官方预编译二进制包要求系统 glibc 至少是 2.28。glibc 是系统最底层的库你不可能随便升级它因为整个操作系统的用户态程序都依赖它强升很容易把系统搞坏。可以先用命令看看当前系统的 glibc 版本ldd --version如果你的系统显示2.27那就要注意Node 18 系列可以正常用Node 20 及以上直接跑官方预编译包大概率会报错。5.2 遇到 GLIBC_2.28 报错怎么办我已经踩过这个坑所以给你几个解决思路按推荐程度排序第一换用 Node 18 LTS。这是最省事的办法绝大多数项目用 Node 18 都能跑也是官方对 Ubuntu 18.04 这类老系统兼容性最好的选择。第二用 Docker 跑新版 Node。把应用容器化宿主机是 Ubuntu 18.04 没关系容器内部可以用 Ubuntu 22.04 甚至更新的基础镜像Node 20、22 都能正常跑。这其实是很多生产环境的最终选择。第三源码编译安装新版 Node。理论上源码编译会链接当前系统的 glibc所以可以绕过预编译包的兼容问题。但编译 Node 对工具链有要求Ubuntu 18.04 自带的 gcc 版本可能偏老需要先升级 gcc、python3、make 等一堆工具编译过程也比较长。如果不是非用新版不可我不太建议在生产环境走这条路。5.3 版本选择实操建议表我根据自己的实际测试和线上稳定性整理了一个针对 Ubuntu 18.04 的版本选择建议目标 Node 版本推荐安装方式风险等级备注Node 16 / 18nvm、NodeSource、二进制包均可低官方兼容性最好建议首选Node 20仅限源码编译或 Docker中官方二进制可能触发 GLIBC_2.28 报错Node 22Docker 容器内运行高不建议直接在宿主机裸装判断逻辑很简单先ldd --version确认 glibc再选 Node 大版本。这样能帮你绕开大部分兼容性事故。6. 常见报错与现场排查实录6.1 安装后 node -v 没反应或提示找不到命令这个问题我遇到太多次了绝大多数都是环境变量没配好。检查思路分三步先看文件是否真的存在ls -l ~/.nvm/nvm.sh ls -l ~/nodejs/bin/node再看PATH里有没有包含对应目录echo $PATH最后看 shell 配置文件有没有写对。nvm 方式装完后新终端才生效当前终端需要手动source。二进制包方式则要确认~/.bashrc里的 export 顺序有没有被后面的语句覆盖。还有一种情况你明明装了但which node显示的却是/usr/bin/node。这说明系统里原先已经有一个 Node而它的目录排在 PATH 更前面。解决办法是调整 PATH 优先级把新目录放在前面或者干脆把老版本卸载掉。6.2 全局安装 npm 包时的权限报错用系统 NodeNodeSource 方式装全局包时经常出现npm ERR! Error: EACCES: permission denied, mkdir /usr/lib/node_modules/xxx原因很简单/usr/lib/node_modules是系统目录普通用户没有写权限。两种解法一种是用 sudo 装sudo npm install -g pm2另一种是给当前用户单独设置 npm 全局目录mkdir -p ~/.npm-global npm config set prefix ~/.npm-global然后在~/.bashrc里加一行export PATH~/.npm-global/bin:$PATH用 nvm 装的 Node 就没有这个问题它的全局目录就在用户主目录下。6.3 node-sass 等老模块编译失败的排查老项目大多依赖 node-sass而 node-sass 在编译时要调用 node-gyp依赖系统里的 Python 和 C 工具链。Ubuntu 18.04 里常见的报错是找不到python命令或者 g 版本不匹配。标准的解决方法是把编译工具链补齐sudo apt install -y build-essential python注意Ubuntu 18.04 默认自带的 Python 2 和 Python 3 都有可能node-gyp 老版本倾向于用python命令所以python这个软链一定要存在。如果项目特别老还可能要用npm install --legacy-peer-deps绕过依赖冲突。更省心的方式是直接换成sass或dart-sass但那种改动要看项目兼容性不能盲目替换。6.4 nvm 下载慢或超时在国内服务器上nvm 从官方源下载 Node 二进制经常慢到让人崩溃。好在 nvm 支持镜像源设置export NVM_NODEJS_ORG_MIRRORhttps://npmmirror.com/mirrors/node/设置完再执行nvm install 18速度会有肉眼可见的提升。也可以把这条 export 写进~/.bashrc避免每次都要输入。还有一个细节nvm 安装脚本本身来自 GitHub如果连 GitHub 都不顺畅可以先手动把 installer 脚本下载下来本地执行或者用代理工具先把脚本内容取回来再去执行bash install.sh。结尾折腾完这一圈我个人最大的体会是在一台 Ubuntu 18.04 上装 Node 高版本问题从来不是“装不上”而是“怎么选一条适合自己的路”。如果只是想快速开发nvm 加 Node 18 LTS 是最稳的组合如果项目要长期以系统服务方式跑NodeSource 源最正规如果服务器安全策略很严格二进制包手动安装才是正解。还有那条硬规则我想再强调一遍先查 glibc再选 Node 版本——这能让你避开 90% 的兼容性坑。最后分享一个小技巧装完 Node 后第一时间顺手把 npm 镜像源切到国内镜像很多后续的闹心问题都能从源头消灭。老服务器也能焕发新生祝你顺利。
阅读完成 · 觉得有帮助?