[英]Running nested commands in Jenkins pipeline shell
我想在 Jenkins 管道中像这样运行嵌套的 shell 命令:
docker stop $(docker ps -aq)
不幸的是,当我将其格式化为管道语法时:
sh('docker stop $(docker ps -aq)')
詹金斯似乎没有正确运行它们,但输出:
"docker stop" requires at least 1 argument(s).
我试图在 bash 下运行命令,就像这里所说的: 在 jenkins 管道上运行 bash 命令但最终遇到了类似的问题。 任何想法如何解决这个问题?
如果将 shell 命令扩展为两行,这对于 Jenkins Pipeline 会变得更容易:
我们使用第一行将 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", " ")
我没有以这种方式使用 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
'''
}
...
添加到@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}"
}
}
}
}
你有没有试过像这样的想法:
docker stop `docker ps -aq`
?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.