☰
Ubuntu 18.04 装高版本 Node.js:nvm/NodeSource/二进制包与 glibc 避坑
2026/10/17 14:49:53 网站建设 项目流程

我前阵子在一台 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文件夹,并把环境变量配置写进.bashrc:

curl -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"

接着就可以安装指定版本的 Node:

nvm 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 一条命令安装并开机自启(systemd)

NodeSource 官方给了一个一键脚本,原理是导入 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] Description=My Node App After=network.target [Service] ExecStart=/usr/bin/node /opt/myapp/app.js Restart=always User=www-data Environment=NODE_ENV=production [Install] WantedBy=multi-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 --depth=0把清单导出来。

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.xz

4.2 以普通用户身份安装的完整操作

解压到用户目录,然后把可执行文件所在的bin目录加进PATH:

mkdir -p ~/nodejs tar -xJf node-v18.20.4-linux-x64.tar.xz -C ~/nodejs --strip-components=1

--strip-components=1的作用是去掉压缩包第一层目录名,让文件直接解压到~/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 包时的权限报错

用系统 Node(NodeSource 方式)装全局包时,经常出现:

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_MIRROR=https://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 镜像源切到国内镜像,很多后续的闹心问题都能从源头消灭。老服务器也能焕发新生,祝你顺利。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询