10

我需要从管道中的文件中读取值。我正在使用split()将它们放入Array中。我需要将它们放入Arraylist中,因此我使用的是Arrays.asList()。我遇到的问题是我无法使用size()length()方法,所以我无法制作一个 for 循环,例如

for (ii = 0; ii < var.length; ii++)

或者

for (ii = 0; ii < var.size; ii++)

因为我收到错误:未分类字段 java.util.Arrays$ArrayList 长度

所以我尝试使用 for each 循环,但是当我在 finally 块中采取一些操作(例如 ls 命令)时,它只迭代 1 次。但是,如果我只是运行命令“echo”,它会像预期的那样对每个元素进行迭代。关于如何修改我的代码以使其在使用任何命令时迭代列表中的每个元素的任何建议?

工作正常....

node{
    wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'dest_hosts.txt', targetLocation: '', variable: 'DEST_HOST']]]) {
        HOST = Arrays.asList(readFile(env.DEST_HOST).split("\\r?\\n"))
        deploy(HOST)
    }
}

@NonCPS
def deploy(host){
    for (String target : host){
        try {
            echo target
        }
        finally {
           echo target
        }
    }
}

输出(迭代每个元素):

[Pipeline] node
Running on <obfuscated>
[Pipeline] {
[Pipeline] wrap
provisoning config files...
copy managed file [<obfuscated>] to file:/var/lib/jenkins/<obfuscated>
[Pipeline] {
[Pipeline] readFile
[Pipeline] echo
www.testhost.com
[Pipeline] echo
www.testhost.com
[Pipeline] echo
www.testhost2.com
[Pipeline] echo
www.testhost2.com
[Pipeline] }
Deleting 1 temporary files
[Pipeline] // wrap
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

但是,如果我采取一些行动,例如“ls -l”,它只会迭代 1 次

node{
    wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'dest_hosts.txt', targetLocation: '', variable: 'DEST_HOST']]]) {
        HOST = Arrays.asList(readFile(env.DEST_HOST).split("\\r?\\n"))
        deploy(HOST)
    }
}

@NonCPS
def deploy(host){
    for (String target : host){
        try {
            echo target
        }
        finally {
           sh 'ls -l'
        }
    }
}

输出(仅迭代 1 次):

[Pipeline] node
Running on <obfuscated>
[Pipeline] {
[Pipeline] wrap
provisoning config files...
copy managed file [<obfuscated>] to file:/var/lib/jenkins/<obfuscated>
[Pipeline] {
[Pipeline] readFile
[Pipeline] echo
www.testhost.com
[Pipeline] sh
[sandbox%2Fpipeline-test-new1] Running shell script
+ ls -l
total 8
-rw-r--r-- 1 jenkins jenkins 10 Jun 17 16:07 someFile
[Pipeline] }
Deleting 1 temporary files
[Pipeline] // wrap
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
4

4 回答 4

9

ArrayList(通常Lists)没有长度或大小字段,它们有size()方法。所以在for中使用它:

for (ii = 0; ii < var.size(); ii++)
于 2016-07-08T05:09:36.940 回答
4

根据本教程:https ://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md#serializing-local-variables

...带有注释的方法@NonCPS... 将被管道引擎视为“本机”,并且它的局部变量永远不会保存。但是它可能不会对流水线步骤进行任何调用

在您的情况下,该sh调用是一个管道步骤操作,您显然无法在带@NonCPS注释的方法中执行该操作。

关于将数组转换为List,那么由于我们在 Groovy 领域,您可以只使用.toList()数组上的方法。

于 2017-08-25T07:34:41.760 回答
2

我更喜欢这个解决方案

node('master') {
    stage('Test 1: loop of echo statements') {
        echo_all(abcs)
    }
}

@NonCPS // has to be NonCPS or the build breaks on the call to .each
def echo_all(list) {
    list.each { item ->
        echo "Hello ${item}"
    }
}

如果您使用声明式管道,则必须将调用包装在脚本语句中:

stage('master') {
    steps {
        script {
            echo_all(abcs);
        }
    }
于 2019-01-31T12:00:45.413 回答
1

我不能准确地告诉你为什么,因为我不知道如何在不花费数小时谷歌搜索的情况下找到有关 Jenkins 的有用信息,但我可以告诉你:

有那么一刻,我认为您可以通过在 sh 'echo $line' 之后添加 'echo line' 来使其运行良好,但事实证明这是由 Jenkins 运行脚本的先前版本引起的......

我尝试了各种各样的东西,但都没有奏效,然后我发现了这个:

为什么 Jenkinsfile 中的每个循环在第一次迭代时停止

它是 Jenkins 管道中的一个已知错误!

(已知的错误是JENKINS-26481,它表示“在工作流插件管理的 Groovy CPS DSL 脚本中,至少有一些闭包只执行一次”)

于 2017-07-17T20:04:29.500 回答