Jenkins中集成NodeJS插件问题对应
发布日期:2021-06-30 20:13:19 浏览次数:2 分类:技术文章

本文共 4545 字,大约阅读时间需要 15 分钟。

在Jenkins的镜像中集成NodeJS插件,发现node和npm都无法执行,最终确认之后定位为libc的问题,在这篇文章中进行memo。中介来说,这个问题还可以描述为:如何在Alpine镜像中支持NodeJS,或者如何在Alpine镜像中使用npm和node。

现象描述

安装了NodeJS插件之后,创建了一个FreeStyle的Job来确认NPM的正常动作

在这里插入图片描述
结果却发现,npm和node获取版本的命令都无法正常动作。

Started by user rootRunning as SYSTEMBuilding in workspace /data/jenkins/workspace/nodejs-freestyle-job[nodejs-freestyle-job] $ /bin/sh -xe /tmp/jenkins8839673353818507589.sh+ npm -venv: ‘node’: No such file or directoryBuild step 'Execute shell' marked build as failureFinished: FAILURE

原因分析

NodeJS插件也是将NodeJS的安装包下载到本地,然后设定PATH所起的作用。经确认,已经成功下载,并且解压后的包的整个大小也使用du命令进行了确认,和官网下载解压下来大小一致。

/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # lsCHANGELOG.md  LICENSE  README.md  bin  include	lib  share/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # ls binnode  npm  npx/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 #

现象是node和npm存在但是运行时提示错误,node较为简单,因为它是一个二进制文件,我们可以通过分析其动态链接库的组成来进行初步的问题确认。

/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # ldd bin/node	/lib64/ld-linux-x86-64.so.2 (0x7efd24f50000)	libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7efd24f50000)	librt.so.1 => /lib64/ld-linux-x86-64.so.2 (0x7efd24f50000)	libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7efd24dfb000)	libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7efd24f50000)	libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7efd24de7000)	libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7efd24f50000)	libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7efd24f50000)Error relocating bin/node: __isinf: symbol not foundError relocating bin/node: __register_atfork: symbol not foundError relocating bin/node: __isnan: symbol not foundError relocating bin/node: backtrace: symbol not found/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 #

而正确的则应该是这样的链接库

[root@liumiaocn bin]# ldd node	linux-vdso.so.1 =>  (0x00007ffd7b0fe000)	libdl.so.2 => /lib64/libdl.so.2 (0x00007f94f0d08000)	librt.so.1 => /lib64/librt.so.1 (0x00007f94f0b00000)	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f94f07f8000)	libm.so.6 => /lib64/libm.so.6 (0x00007f94f04f6000)	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f94f02e0000)	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f94f00c3000)	libc.so.6 => /lib64/libc.so.6 (0x00007f94efcf5000)	/lib64/ld-linux-x86-64.so.2 (0x0000563624981000)[root@liumiaocn bin]#

基本可以断定这是Alpine镜像特有的问题,因为其使用的非libc而是musl。以下记录一下常见的解决方法。

对应方法1: 换掉Alpine镜像

使用glibc为基础的镜像比如CentOS,常见发行版的Linux基本都没有这个问题,即可解决这个问题,但是Alpine镜像非常小的这个利点也随之而去。

对应方法2: 添加相关的依赖

理论上来说,添加ldd提示的所缺少的动态链接库中缺少的内容,应该能够解决这个问题。基于musl的Alpine中安装glibc是一个很奇怪的想法,但是github上确实存在这样一种解决方案。之前使用这种方式成功地解决了Oracle发行版的JDK的Alpine镜像的类似问题。但是单纯安装响应的glibc的包到Alpine镜像中,显然没有能够直接解决这个问题,memo信息如下:

步骤1: 下载key

执行命令:

apk --no-cache add ca-certificates wget
wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub

执行日志如下所示

~ # apk --no-cache add ca-certificates wgetfetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gzfetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz(1/1) Installing wget (1.20.3-r0)Executing busybox-1.29.3-r10.triggerOK: 350 MiB in 112 packages~ # wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub~ #

步骤2: 下载apk安装文件

执行命令:

wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.30-r0/glibc-2.30-r0.apk

步骤3: 安装

执行命令:apk add glibc-2.30-r0.apk

执行日志如下所示:

~ # lsglibc-2.30-r0.apk~ # apk add glibc-2.30-r0.apk fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz(1/1) Installing glibc (2.30-r0)OK: 359 MiB in 113 packages~ #

结果问题仍然存在。另外重新安装了了libstdc++和libgcc仍然没有解决这个问题。不存在的情况下,动态链接库会有如下错误提示:

Error loading shared library libstdc++.so.6: No such file or directory (needed by node)Error loading shared library libgcc_s.so.1: No such file or directory (needed by node)

虽然此路暂未走通,但是应该存在这样一种方式解决。

对应方法3: 使用基于libc版本的NodeJS发行版(源码生成方式)

从NodeJS插件使用中可以看到,如果设定的是从nodejs.org获取安装的情况下,使用的时候会发现诸如下列的执行日志信息:

Unpacking https://nodejs.org/dist/v8.6.0/node-v8.6.0-linux-x64.tar.gz to /data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 on Jenkins

从中可以清楚的看到,此NodeJS插件是从官方下载了相应的压缩包,然后展开,仅此而已。

而目前的官方的NodeJS所提供的下载,并没有直接有Alpine Linux可以直接使用的二进制文件,所以可以使用Alpine容器中手动从源码生成的方式,然后将生成的二进制内容拷贝到JENKINS_HOME 下的tools下的响应路径的NodeJS予以替换即可。

对应方法4: 使用Alpine的nodejs包

Alpine的nodejs包,使用apk add nodejs即可。使用方式可以参看如下内容:

  • https://liumiaocn.blog.csdn.net/article/details/102595065

但是限制在于版本的支持是特定的,如有特定版本的需求仍然需要从源码编译的方式进行解决。

转载地址:https://liumiaocn.blog.csdn.net/article/details/102587460 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:ng-alain使用中的路由部分自动代码生成的一个问题
下一篇:ng-alain中的husky使用问题与解决

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月14日 07时27分49秒