本文共 5713 字,大约阅读时间需要 19 分钟。
这篇文章介绍一种较为拧巴的方式纠结地解决Alpine版本的Jenkins的NodeJS插件使用中所出现的No such file or directory的问题的对应方法。
现象描述
安装了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 # 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 #
在glibc的操作系统上,链接库是这样的。
[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]#
对应方法1: 使用源码编译的二进制进行替换
步骤1: 在Alpine容器中使用源码编译nodejs
如何使用源码在Alpine容器中编译nodejs,可参看下文:
- 链接: https://liumiaocn.blog.csdn.net/article/details/102598121
步骤2: 将Alpine容器中的如下目录的内容进行tar文件打包
/usr/local # lsbin include lib share/usr/local #
步骤3: 将tar包内容替换Jenkins根目录下对应的nodejs的内容
- 删除原有内容
/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 # rm -rf */data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 #
- 将上述Alpine的内容在此处展开
/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # tar xf /tmp/node.tar /data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # lsbin include lib share/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # ```
- 结果确认
/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # ./bin/node -vv8.6.0/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # ./bin/npm -v5.3.0/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 #
NodeJS插件动作确认
在Jenkins中再次执行安装了NodeJS插件的Job,查看Job的输出,则发现已经可以正常输出结果了。
Started by user rootRunning as SYSTEMBuilding in workspace /data/jenkins/workspace/nodejs-freestyle-job[nodejs-freestyle-job] $ /bin/sh -xe /tmp/jenkins2940196791294240736.sh+ npm -v5.3.0+ node -vv8.6.0Finished: SUCCESS
对应方法2: 使用已经Alpine镜像中的二进制包替代
这种方式跟方法1基本相同,那就是来源不需要进行源码编译了,使用别人编译好的也可以。比如Easypack中已经打好的,实际上你看一下Dockerfile就会立即发现,其实也是通过源码下载然后configure&&make&&make install后生成的。以10.15.3的lts版为例进行说明:
步骤1: 获取替换用的nodejs的tar包
- 拉取镜像,并确认node和npm的版本信息
liumiaocn:~ liumiao$ docker pull liumiaocn/nodejs:10.15.310.15.3: Pulling from liumiaocn/nodejsDigest: sha256:6a2681be36f2b52ab2c1b39066719bdd151cd39115e39884bffe397721f1fc85Status: Image is up to date for liumiaocn/nodejs:10.15.3liumiaocn:~ liumiao$ docker run --name node -it liumiaocn/nodejs:10.15.3 sh/ # which node/usr/local/bin/node/ # node -vv10.15.3/ # npm -v6.4.1/ #
- 生成替换用的tar包
/ # cd /usr/local/usr/local # lsbin include lib share/usr/local # tar cvpf /tmp/nodejs.10.15.3.tar ....省略./include/node/config.gypi./include/node/v8-util.h/usr/local # ls /tmp/nodejs.10.15.3.tar /tmp/nodejs.10.15.3.tar/usr/local #
步骤2: 设定Jenkins的工具配置
在Jenkins的Global Tool Configuration中进行如下设定
步骤3: 将tar包展开并确认版本
进入到Jenkins的容器中创建上述配置中的目录,并将此作为NodeJS的根目录,将步骤1中生成的tar文件进行展开。Jenkins容器中的执行示例日志如下所示
/ # mkdir -p /usr/local/node/10.15.3/ # cd /usr/local/node/10.15.3/usr/local/node/10.15.3 # tar xvpf /tmp/nodejs.10.15.3.tar ...省略./include/node/config.gypi./include/node/v8-util.h/usr/local/node/10.15.3 # lsbin include lib share/usr/local/node/10.15.3 # ./bin/node -vv10.15.3/usr/local/node/10.15.3 # ./bin/npm -v6.4.1/usr/local/node/10.15.3 # /usr/local/node/10.15.3 # ldd ./bin/node /lib/ld-musl-x86_64.so.1 (0x7f8dcf592000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7f8dcd4e8000) libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f8dcd4d4000) libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f8dcf592000)/usr/local/node/10.15.3 #
总结
虽然这种方式比较拧巴,但是至少比在Alpine中安装glibc最终实现目的的效果要好一点。可以看到这种方式之下链接库至少是正常地使用musl的。
/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 # ldd bin/node /lib/ld-musl-x86_64.so.1 (0x7f844e493000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7f844c51a000) libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f844c506000) libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f844e493000)/data/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/nodejs-8.6.0 #
拧巴的方式有两种,相较于第一种自动生成在JENKINS_HOME下的tools的来源于官网或者其他URL的nodejs下手,第二种方式略显自然一点,而且也不必要求联网,但是就是第一次操作之前有些手动设定作业。
转载地址:https://liumiaocn.blog.csdn.net/article/details/102614730 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!