【问题标题】:Running nested commands in Jenkins pipeline shell在 Jenkins 管道 shell 中运行嵌套命令
【发布时间】:2017-11-20 12:39:41
【问题描述】:

我想在 Jenkins 管道中运行嵌套的 shell 命令,例如:

docker stop $(docker ps -aq)

不幸的是,当我将其格式化为管道语法时:

sh('docker stop $(docker ps -aq)')

Jenkins 似乎没有正确运行它们,但输出:

"docker stop" requires at least 1 argument(s).

我尝试在 bash 下运行命令,如下所示: Run bash command on jenkins pipeline 但最终会遇到类似的问题。任何想法如何解决这个问题?

【问题讨论】:

  • 您可以接受将这一行从一行扩展到两行的解决方案吗?
  • 我也很好

标签: shell jenkins jenkins-pipeline


【解决方案1】:

如果将 shell 命令扩展为两行,这对 Jenkins Pipeline 来说会变得更容易:

  • 第一个捕获要停止的 Docker 容器。
  • 第二个停止在第一个命令中捕获的那些 Docker 容器。

我们使用第一行将shell命令的输出捕获到一个变量中:

containers = sh(returnStdout: true, script: 'sudo /usr/bin/docker ps -aq')

然后我们使用第二个命令对存储在变量中的第一个命令的捕获输出进行操作:

sh("sudo /usr/bin/docker stop $containers")

请注意,docker 命令通常对 docker ps -aq 的输出感到满意,以便与其他命令一起操作,但如果它不喜欢存储在变量中的输出,您可以像下面这样重新格式化它:

containers = sh(returnStdout: true, script: 'sudo /usr/bin/docker ps -aq').trim()

例如,这将去除前导空格和尾随换行符。 Docker CLI 通常不关心这一点,但这里可能需要进行一些重新格式化。

由于在此处删除换行符会导致组合容器 ID 很长,因此我们需要(如您所述)将其替换为空格以分隔容器 ID。这将格式化存储在containers 变量中的字符串:

containers = sh(returnStdout: true, script: 'sudo /usr/bin/docker ps -aq').replaceAll("\n", " ")

【讨论】:

  • 感谢马特的建议。我似乎詹金斯将命令的输出作为命令运行。我收到以下错误:[build-abc-pipeline-TEST] Running shell script + docker ps -aq [Pipeline] sh [build-abc-pipeline-TEST] Running shell script + docker stop b21b1d2a85a2 b21b1d2a85a2 + 4c8e17511fd1 /var/lib/jenkins/workspace/abc-TEST@tmp/durable-27835dc3/script.sh: line 3: 4c8e17511fd1: command not found 看起来输出(容器 ID)作为 shell 命令运行?
  • @MaksimLuzik 所以它工作得很好,但是关于格式的警告似乎是真的,所以你需要听从我的建议。
  • 你是对的,马特,docker ps -aq 将每个容器 ID 作为其自己的行返回,Jenkins 从第二行开始运行 ID 作为命令。我不得不用空格替换新行以使其工作,如下所示:docker ps -aq |tr "\n" " "
  • @MaksimLuzik 所以看起来.trim() 会是一个问题,因为它只是删除换行符并且不插入空格,这会导致长组合容器ID,这没有帮助。 .replaceAll("\n", " ") 最终会成为你的内在。稍后更新答案。
【解决方案2】:

我没有以这种方式使用过 docker stop 命令,但 docker rm 命令的语法相同。管道代码块 + OP 的行例如:

...
    withEnv(["port=$port", "user=$user", "env=$env"]) {
        sh '''
            ssh -p $port $user@$env docker rm \$(docker ps -aq) || true; \
            ssh -p $port $user@$env docker rmi \$(docker images -aq) || true; \
            ssh -p $port $user@$env docker stop \$(docker ps -aq) || true
        '''
    }
...

【讨论】:

    【解决方案3】:

    添加到@Matt 的答案,

    您需要检查空容器。如果没有容器可以停止,Jenkins 构建将失败并抛出以下错误消息

    "docker stop" requires at least 1 argument(s).

    要处理这个问题,您只需要检查容器的可用性。这是完整的代码

            stage('Clean docker containers'){
                steps{
                    script{
                    
                        def doc_containers = sh(returnStdout: true, script: 'docker container ps -aq').replaceAll("\n", " ") 
                        if (doc_containers) {
                            sh "docker stop ${doc_containers}"
                        }
                        
                    }
                }
            }
    

    【讨论】:

      【解决方案4】:

      你有没有尝试过这样的想法:

      docker stop `docker ps -aq`
      

      ?

      【讨论】:

        最近更新 更多