背景
运维群里的一个小伙伴在群里提问:
哪位大侠知道jenkins上出现这种情况一般是怎么回事呢?shell脚本在执行机器上手动执行OK,但通过在jenkisn‘的执行shell窗口输入命令行的方式进去之后就会出现乱七八糟的问题了
我以为是以前遇到的读不到环境变量的问题,便回答:
Jenkins貌似读不到机器上的环境变量 如果你是添加了些node_env这样的 你最好在Jenkins的命令那export一下
因为以前遇到过,测试环境的node程序是读取node_env这样的变量,来分辨测试环境和正式环境,但是Jenkins似乎不能读取/etc/profile这样的环境变量配置文件。
所以我是在脚本前export一下。
然后第二天,小伙伴私聊我,并贴出了问题截图
昨天那个问题 我在本地机器上执行pushd 没有问题的,但是我通过jenkins的执行shell的窗口去执行这个就会报错说 pushd not found
解决方案
我先给出解决方案,再说排查问题的过程。
解决方案是把sh
替换为bash
.
参考:https://blog.csdn.net/robertbaker/article/details/21129517
执行sudo dpkg-reconfigure dash
,选择no。
再看/bin/sh
是否被链接到bash
1 | ls -lh /bin/sh |
Jenkins 再执行命令没有报错,问题解决。
排查问题过程
核心问题在于找不到命令。那我们就帮助 Jenkins 找到命令的位置就可以了,这是我最开始的思路。
一旦找到了,用绝对路径执行,或者alias
,export
这些,都可以解决。
我让他 which
或者 whereis
一下,看看pushd
这个命令的绝对路径。
小伙伴回复:
which pushd 在本地执行是空的输出
诶,那这个pushd
是哪来的,那就find / -name pushd
找吧
嗯 有点怪 我执行find 去pushd 居然说权限不对 我已经是root了
我心想难道是unix那套系统,freebsd什么的(?。。
ubuntu的
难道是build-in的命令,然后在自己电脑上试了下,惊了!还真是。。(mdzz 我真是鱼唇
这样的话,which
/whereis
/find
当然找不到了
但是他说
本机执行没问题,Jenkins执行就找不到
那么,还是解析器(interpreter) 的锅,因为Jenkins执行脚本用的/bin/sh
参考:https://stackoverflow.com/questions/5193048/bin-sh-pushd-not-found
pushd
is abash
enhancement to the POSIX-specified Bourne Shell.pushd
cannot be easily implemented as a command, because the current working
directory is a feature of a process that cannot be changed by child
processes.
pushd
是bash
的内建命令,sh
那种精简的解析器执行就会找不到。
所以必须要用bash来执行脚本,而Jenkins只能用sh
来执行脚本,这点好像是没法改变的。
那我们就把bash
链接到sh
,这样Jenkins执行sh -xe xxx.sh
,实际上是执行bash。