开发者问题收集

Jenkins 使用 docker.image.withRun 通过 sh 执行第二条命令

2022-04-15
362

我目前有一个 Jenkins 脚本,它启动一个 Docker 容器,其中使用 Maven 运行 Selenium 测试。 Selenium 测试执行成功,Maven 返回“构建成功”。

问题如下:Jenkins 不仅执行 Jenkinsfile 中指定的 sh 命令,还执行了未知的第二个 sh 命令。

Jenkins 管道步骤

如图所示,突出显示的部分作为命令执行,这显然不是命令,这意味着 Docker 容器返回错误代码 127。

Jenkinsfile:

node {
    stage('Checkout Code') {
        checkout scm
    }
    try {
        withEnv(["JAVA_HOME=${tool 'JDK 11.0'}", "PATH+MAVEN=${tool 'apache-maven-3.x'}/bin", "PATH+JAVA=${env.JAVA_HOME}/bin"]) {
            stage('Run Selenide Tests') {
                docker.image('selenium/standalone-chrome').withRun('-v /dev/shm:/dev/shm -P') { c->
                    sh "mvn clean test -Denvironment=${env.Profile} -Dselenide.headless=true -Dselenide.remote=http://" + c.port(4444) + "/wd/hub"
                }
            }
        }
    }catch(e){
        currentBuild.result = "FAILURE"
        throw e
    } finally {
        stage('Notify Slack Channel of Tests status') {
            // Hidden
        }
    }
}

控制台输出(某些部分由于不相关而被隐藏):

+ docker run -d -v /dev/shm:/dev/shm -P selenium/standalone-chrome
+ docker port a15967ce0efbda908f6ba9bb7c8c633bb64e54a6557e5c23097ea47ed0540ff9 4444
+ mvn clean test -Denvironment=jenkins -Dselenide.headless=true -Dselenide.remote=http://0.0.0.0:49827
// Maven tests
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:14 min
[INFO] Finished at: 2022-04-14T15:36:38+02:00
[INFO] ------------------------------------------------------------------------
+ :::49821/wd/hub
/var/lib/jenkins/workspace/selenide-tests/test@tmp/durable-58ae7b8f/script.sh: 2: 
/var/lib/jenkins/workspace/selenide-tests/test@tmp/durable-58ae7b8f/script.sh: :::49821/wd/hub: not found
+ docker stop a15967ce0efbda908f6ba9bb7c8c633bb64e54a6557e5c23097ea47ed0540ff9
a15967ce0efbda908f6ba9bb7c8c633bb64e54a6557e5c23097ea47ed0540ff9
+ docker rm -f a15967ce0efbda908f6ba9bb7c8c633bb64e54a6557e5c23097ea47ed0540ff9
a15967ce0efbda908f6ba9bb7c8c633bb64e54a6557e5c23097ea47ed0540ff9
ERROR: script returned exit code 127
Finished: FAILURE

这是一个常见问题,很容易解决,还是我的 Jenkinsfile 有问题,我该如何修复?

谢谢

2个回答

看来 /wd/hub 部分来自您执行的代码行,这让我相信您的问题是由于您添加引号的方式造成的。 您的代码行是:

sh "mvn clean test -Denvironment=${env.Profile} -Dselenide.headless=true -Dselenide.remote=http://" + c.port(4444) + "/wd/hub"

具体来说,您使用 " 打开命令,然后在 http:// 之后使用另一个 " 关闭它。我猜詹金斯认为这不可接受。尝试单独创建网址

def url = "http://" + c.port(4444) + "/wd/hub"

并在执行行中使用此变量

sh "mvn clean test -Denvironment=${env.Profile} -Dselenide.headless=true -Dselenide.remote=${url}"

我以前没有使用过 docker.image ,所以您可能需要尝试一下才能使其正常工作。

M B
2022-04-15

在进一步研究文档并尝试不同的东西之后,这是对我有用的:

node {
    stage('Checkout Code') {
        checkout scm
    }
    try {
        withEnv(["JAVA_HOME=${tool 'JDK 11.0'}", "PATH+MAVEN=${tool 'apache-maven-3.x'}/bin", "PATH+JAVA=${env.JAVA_HOME}/bin"]) {
            stage('Run Selenide Tests') {
                docker.image('selenium/standalone-chrome').withRun('-v /dev/shm:/dev/shm -p 4444:4444') { 
                    def selenideRemote = "http://0.0.0.0:4444/wd/hub"
                    sh "mvn clean test -Denvironment=${env.Profile} -Dselenide.headless=true -Dselenide.remote=${selenideRemote}
                }
            }
        }
    }catch(e){
        currentBuild.result = "FAILURE"
        throw e
    } finally {
        stage('Notify Slack Channel of Tests status') {
            // Hidden
        }
    }
}

所以我用 .withRun(-v /dev/shm:/dev/shm -p 4444:4444') 替换 .withRun('-v /dev/shm:/dev/shm -P') ,并用 selenideRemote 变量替换 c.port(4444)

删除 c.port(4444) 会停止执行有问题的第二个命令。将 -P 替换为 -p 4444:4444 可防止将容器内部的端口 4444 分配给主机上的随机端口,这也防止使用 c.port(4444)

jop.verhoeven
2022-04-19