Jenkins声明性流水线中找不到Bash

3
我有一个问题,Jenkins无法识别bash。 我使用golang镜像运行docker代理的stage。尝试运行sh文件时,我收到以下错误: + ./build/docker/docker.sh /home/jenkins/workspace/003-CGI-App-setup-ACS-build-4ZEA3UO3JRWIGZRIGIBD7BRQJV7JJ4LAKTS4XDXT6N3GDVU7Z4WA@tmp/durable-46264c73/script.sh: line 1: ./build/docker/docker.sh: not found 这是我的stage:
stage('Build & publish') {
        agent {
            docker {
                image 'golang:1.10-alpine3.7'
            }
        }
        steps {
            checkout scm
            unstash 'war'
            sh 'export PATH=/bin/bash:$PATH'
            sh 'cp XXX/XXX/target/*.war build/docker/ROOT.war'
            sh 'chmod 777 ./build/docker/docker.sh'
            sh 'go build -o XXX'
            sh './XXX build'
            sh './build/docker/docker.sh'
        }
    }

我的docker.sh文件也以#!/bin/bash开头。

有人知道这是否与docker镜像有关吗?如果是,我是否正确添加了bash?

谢谢。

1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
6
许多轻量级的Docker镜像,尤其是基于Alpine Linux构建的镜像,不包含GNU Bash。 这里最好的解决方案是重新编写脚本,不特别要求使用bash。将它的shebang行更改为#!/bin/sh,并将其语法限制在POSIX shell规范允许的范围内。对于大多数直接进行"A、B、C,然后D"式脚本,这已经足够了。如果你发现自己需要使用bash特定的功能,比如数组,请考虑使用更强大的脚本语言,如Python。 具体来说,在单行中:
sh 'export PATH=/bin/bash:$PATH'
  • 每个sh命令都在其自己的执行环境中运行,有一个干净的环境,因此早期sh语句中的环境变量设置不会影响后来的语句;这个语句不起任何作用。
  • $PATH的元素是目录,而不是单个文件。
  • /bin几乎是必须在$PATH上,并且它在所有标准执行环境中都存在。(如果存在/bin/bash,那么显式的bash -c '...'命令和#!/bin/bash shebang行将找到它。)

(这种问题的另一个常见原因是混合的Windows/Linux环境,其中实际的shebang行以DOS风格的CR/LF两个字符换行符结束,而环境无法运行/bin/bash\r。)


1
尽管此答案中的所有信息都是正确的,但实际上它并不是他问题的根本原因,因为它源于 Jenkins 问题而不是 Docker 问题。真正的问题在于他试图访问 Jenkins 工作区中不存在的 ./build/docker/docker.sh,因为出于某种原因它不在 Docker 镜像中。 - Matt Schuchard
如果已经将其检入源代码存储库,则“checkout scm”步骤应该使其可用?但是,是的,这是一个重要的观点。 - David Maze
是的,如果它被检入SCM,它应该被放入工作区。然而,在Jenkinsfile中似乎缺少checkout([$class: 'GitSCM'...])或类似的特定信息(只是伪代码)。这里似乎缺少具体细节。另一方面,如果sh不存在,则chmod将失败,所以现在我更倾向于同意您的答案。 - Matt Schuchard
谢谢大家的回答。我通过存储构建文件并在单独的阶段运行脚本来解决了这个问题。我发现Docker镜像不允许使用bash。 - ZaCH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,