背景

运维群里的一个小伙伴在群里提问:

哪位大侠知道jenkins上出现这种情况一般是怎么回事呢?shell脚本在执行机器上手动执行OK,但通过在jenkisn‘的执行shell窗口输入命令行的方式进去之后就会出现乱七八糟的问题了

我以为是以前遇到的读不到环境变量的问题,便回答:

Jenkins貌似读不到机器上的环境变量 如果你是添加了些node_env这样的 你最好在Jenkins的命令那export一下

因为以前遇到过,测试环境的node程序是读取node_env这样的变量,来分辨测试环境和正式环境,但是Jenkins似乎不能读取/etc/profile这样的环境变量配置文件。

所以我是在脚本前export一下。

然后第二天,小伙伴私聊我,并贴出了问题截图

quest
quest

昨天那个问题 我在本地机器上执行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
2
ls -lh /bin/sh
lrwxrwxrwx 1 root root 4 Sep 18 15:33 /bin/sh -> bash

Jenkins 再执行命令没有报错,问题解决。

排查问题过程

核心问题在于找不到命令。那我们就帮助 Jenkins 找到命令的位置就可以了,这是我最开始的思路。

一旦找到了,用绝对路径执行,或者aliasexport这些,都可以解决。

我让他 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 a bash 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.

pushdbash的内建命令,sh那种精简的解析器执行就会找不到。

所以必须要用bash来执行脚本,而Jenkins只能用sh来执行脚本,这点好像是没法改变的。

那我们就把bash链接到sh,这样Jenkins执行sh -xe xxx.sh,实际上是执行bash。