适用系统:CentOS 7 / RHEL 7 / TencentOS Server 2.x 适用场景:系统 glibc 版本低(2.17),直接安装 Node18 报错时。
一、问题背景
CentOS 7 默认使用 glibc 2.17,而 Node.js 18 及以上版本需要:
GLIBC_2.25/GLIBC_2.27/GLIBC_2.28GLIBCXX_3.4.20/GLIBCXX_3.4.21/CXXABI_1.3.9
如果直接安装 Node18,会出现如下错误:
node: /lib64/libm.so.6: version `GLIBC_2.27' not found
node: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
二、安装必要工具
配置阿里云 Yum 源
sudo cat /etc/yum.repos.d/CentOS-Base.repo <<'EOF'
[base]
name=CentOS-7 - Base - aliyun
baseurl=http://mirrors.aliyun.com/centos/7/os/x86_64/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
[updates]
name=CentOS-7 - Updates - aliyun
baseurl=http://mirrors.aliyun.com/centos/7/updates/x86_64/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
[extras]
name=CentOS-7 - Extras - aliyun
baseurl=http://mirrors.aliyun.com/centos/7/extras/x86_64/
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
EOF
yum makecache
安装开发工具
yum install -y wget curl git gcc gcc-c++ make python3 openssl-devel zlib-devel
# 安装新版make
# 1) 安装编译依赖
sudo yum groupinstall -y "Development Tools"
sudo yum install -y wget tar
# 2) 下载并编译 make(示例用 4.4.1)
cd /tmp
wget https://ftp.gnu.org/gnu/make/make-4.4.1.tar.gz
tar xf make-4.4.1.tar.gz
cd make-4.4.1
# 3) 安装到 /opt/make-4.4,不覆盖系统的 /usr/bin/make
./configure --prefix=/opt/make-4.4
make -j"$(nproc)"
sudo make install
# 4) 让新 make 优先生效(当前会话)
export PATH=/opt/make-4.4/bin:$PATH
hash -r
make --version # 应显示 4.4.1(或你安装的版本)
三、安装 GCC 8(通过 devtoolset-8)
yum install -y centos-release-scl
yum install -y devtoolset-8 devtoolset-8-toolchain devtoolset-8-libstdc++-devel
scl enable devtoolset-8 bash
gcc --version
四、编译并安装 glibc 2.28(不覆盖系统)
cd /usr/local/src
wget https://ftp.gnu.org/gnu/libc/glibc-2.28.tar.gz
tar -xzf glibc-2.28.tar.gz
# 2) 设定源码与构建目录变量
SRC=/usr/local/src/glibc-2.28
BUILD=/usr/local/src/glibc-2.28-build
# 3) 新建干净的构建目录
rm -rf "$BUILD" && mkdir -p "$BUILD"
cd "$BUILD"
# 4) 确保用新 make
export PATH=/opt/make-4.4/bin:$PATH
hash -r
# 5) 运行 configure(指向 *正确的* 源码路径)
MAKE=/opt/make-4.4/bin/make \
GNUMAKE=/opt/make-4.4/bin/make \
"$SRC"/configure \
--prefix=/opt/glibc-2.28 \
--enable-obsolete-nsl \
--disable-werror \
--cache-file=/dev/null
# 6) 编译与安装(并行度可按机器调低,比如 -j2)
make -j"$(nproc)"
sudo make install
mkdir -p /opt/glibc-2.28/etc
echo -e "/opt/glibc-2.28/lib\n/opt/rh/devtoolset-8/root/usr/lib64" > /opt/glibc-2.28/etc/ld.so.conf
/opt/glibc-2.28/sbin/ldconfig -r /opt/glibc-2.28
五、安装 Node.js 18(使用 nvm)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install 18.19.1
nvm alias default 18.19.1
六、创建兼容 Node18 的“包装器”
mv ~/.nvm/versions/node/v18.19.1/bin/node ~/.nvm/versions/node/v18.19.1/bin/node.real
cat > ~/.nvm/versions/node/v18.19.1/bin/node <<'EOF'
#!/usr/bin/env bash
NODE_REAL="/root/.nvm/versions/node/v18.19.1/bin/node.real"
GLIBC="/opt/glibc-2.28"
LIBS="/opt/gcc8/lib64:/opt/glibc-2.28/lib:/lib64:/usr/lib64"
exec "$GLIBC/lib/ld-linux-x86-64.so.2" --library-path "$LIBS" "$NODE_REAL" "$@"
EOF
chmod +x ~/.nvm/versions/node/v18.19.1/bin/node
验证:
node -v
npm -v
npx -v
七、可选:系统级 npm 包装器
sudo tee /usr/local/bin/npm >/dev/null <<'EOF'
#!/usr/bin/env bash
NODE_HOME="/root/.nvm/versions/node/v18.19.1"
GLIBC="/opt/glibc-2.28"
LIBPATH="$GLIBC/lib:/opt/gcc8/lib64:/lib64:/usr/lib64"
exec "$GLIBC/lib/ld-linux-x86-64.so.2" --library-path "$LIBPATH" "$NODE_HOME/bin/node" "$NODE_HOME/lib/node_modules/npm/bin/npm-cli.js" "$@"
EOF
chmod +x /usr/local/bin/npm
八、永久生效
echo 'export PATH="/usr/local/bin:/opt/node18-shim/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
九、自检
/opt/glibc-2.28/lib/ld-linux-x86-64.so.2 --list "$(which node)" | egrep 'libc|libstdc'
输出应为:
libc.so.6 => /opt/glibc-2.28/lib/libc.so.6
libstdc++.so.6 => /opt/gcc8/lib64/libstdc++.so.6
十、备份当前可用状态
tar czf /root/node18-working-backup.tgz /opt/glibc-2.28 /opt/gcc8 ~/.nvm/versions/node/v18.19.1/bin/node ~/.nvm/versions/node/v18.19.1/bin/node.real
最终验证
node -v
npm -v
npm run build
更新包装器脚本
#!/usr/bin/env bash
VER=${1:-v18.19.1}
NODE_HOME="$HOME/.nvm/versions/node/$VER"
mv "$NODE_HOME/bin/node" "$NODE_HOME/bin/node.real"
cat >"$NODE_HOME/bin/node" <<EOF
#!/usr/bin/env bash
NODE_REAL="$NODE_HOME/bin/node.real"
GLIBC="/opt/glibc-2.28"
LIBS="/opt/gcc8/lib64:/opt/glibc-2.28/lib:/lib64:/usr/lib64"
exec "\$GLIBC/lib/ld-linux-x86-64.so.2" --library-path "\$LIBS" "\$NODE_REAL" "\$@"
EOF
chmod +x "$NODE_HOME/bin/node"
echo "Node $VER wrapper rebuilt successfully!"