案发:
最近遇到个问题,当你jenkins服务器上运维因为各种原因不愿意装nvm或者n等版本控制升级node而系统默认版本一直是超低版本的node。想指定node运行版本怎么办呢?
之前大佬们遗留的jenkins脚本是这样写得:
再看看run build的script是怎么写的:
然后喜闻乐见,打包无限失败:
查了一下说是node版本问题,但看上去没问题啊,已经是node-v12了,跟本地的node版本一致啊,那究竟怎么办呢,本地打包直接发布,让我带你们一步一步解开谜题
疑云
乍一看没问题,通过服务器上绝对路径启动指定版本npm运行srcipt脚本,但是,当我们把build:test加一个"node -v"就会发现,
这是怎么回事呢,为什么我指定了npm版本,node却是系统的v8.x呢?但事实就是这样,小编也感到非常惊讶。
线索
随后小编就查一下npm run的相关资料,发现这样两句话:
In addition to the shell's pre-existing PATH, npm run adds node_modules/.bin to the PATH provided to scripts. Any binaries provided by locally-installed dependencies can be used without the node_modules/.bin prefix. The actual shell your script is run within is platform dependent. By default, on Unix-like systems it is the /bin/sh command, on Windows it is the cmd.exe. The actual shell referred to by /bin/sh also depends on the system. As of npm@5.1.0 you can customize the shell with the script-shell configuration.
原来在你执行script的时候,会自动将“node_modules/.bin”作为前缀,查找到你这条命令对应的脚本,比如vue-cli-service对应的是“node_modules/.bin/vue-cli-service”然后根据平台环境通过不同的默认shell执行脚本。并不是在启动npm当时的那个shell中执行。
破案
翻译一下在服务端输入“/usr/local/node-v12.9.1-linux-x64/bin/npm run build:test”用这段话打包的时候会发生什么,就很清楚了
- 使用node-12自带的npm模块执行run build:test
- build:test对应的脚本即"cross-env CUSTOM_ENV=test vue-cli-service build"
- 通过系统默认shell(未指定时)执行脚本。
- 以vue-cli为例,sh的脚本长这样:
- vue-cli的打包脚本是怎么跑的因为篇幅原因我就不多讲了,这不属于我的知识范畴本文内容。
解决
但看懂了这段,应该对怎么解决有了很多办法:
可以自己写个.sh的脚本,Jenkins的bash中的直接执行该脚本,同样以vue-cli-serve脚本中的一行为例,比如:将node "$basedir/../@vue/cli-service/bin/vue-cli-service.js" "$@"改为/usr/local/node-v12.9.1-linux-x64/bin/node "$basedir/../node_modules/@vue/cli-service/bin/vue-cli-service.js" "$@",注意添加node_modules即可
可以在script中直接写死,Jenkins执行shell不变,直接npm run build:test:
"scripts": { "build:test": "cross-env CUSTOM_ENV=test /usr/local/node-v12.9.1-linux-x64/bin/node 'node_modules/@vue/cli-service/bin/vue-cli-service.js' build", },复制代码
拉着运维的手求他装个nvm/n不装不让办公