Groovy 报告说,当文件确实存在于系统中时,该文件并不存在

Groovy reports that a file doesn't exists when it really is present in the system

提问人:Adri C.S. 提问时间:1/19/2017 更新时间:12/17/2021 访问量:26247

问:

每当我的 Jenkins 作业构建完成时,我都会使用插件(又名 插件)。 此外,如果系统中存在某个文件,我将修改消息的默认内容以通知该文件的存在。Editable Email NotificationEmail-ext

为此,我使用了插件的字段。Pre-send Script

测试作业配置:

为运行准备环境

属性内容

LOG="log.txt"

构建阶段

执行 shell

#!/bin/bash

touch ${WORKSPACE}/${LOG}
echo "this is just a log" >> ${WORKSPACE}/${LOG}

生成后操作

可编辑的电子邮件通知

预发送脚本

File log = new File("${WORKSPACE}/${LOG}");
logger.println(log.text);

执行构建时,将在 中创建文件并填充它(我能够从 Jenkins slave 中的终端打印内容)。Jenkins${WORKSPACE}

但是当尝试从插件访问它时,会引发异常:Emailjava.io.FileNotFoundException

java.io.FileNotFoundException: /home/jenkins/workspace/testJob/log.txt (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:146)
    at groovy.util.CharsetToolkit.<init>(CharsetToolkit.java:69)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.newReader(DefaultGroovyMethods.java:16958)
    at org.codehaus.groovy.runtime.DefaultGroovyMethods.getText(DefaultGroovyMethods.java:16006)
    at org.codehaus.groovy.runtime.dgm$381.doMethodInvoke(Unknown Source)
    at org.codehaus.groovy.reflection.GeneratedMetaMethod$Proxy.doMethodInvoke(GeneratedMetaMethod.java:70)
    at groovy.lang.MetaClassImpl$GetBeanMethodMetaProperty.getProperty(MetaClassImpl.java:3500)
    at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:61)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
    at Script1.run(Script1.groovy:59)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:580)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:618)
    at groovy.lang.GroovyShell.evaluate(GroovyShell.java:589)
    at hudson.plugins.emailext.ExtendedEmailPublisher.executePresendScript(ExtendedEmailPublisher.java:450)
    at hudson.plugins.emailext.ExtendedEmailPublisher.sendMail(ExtendedEmailPublisher.java:311)
    at hudson.plugins.emailext.ExtendedEmailPublisher._perform(ExtendedEmailPublisher.java:297)
    at hudson.plugins.emailext.ExtendedEmailPublisher.perform(ExtendedEmailPublisher.java:244)
    at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20)
    at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:782)
    at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:723)
    at hudson.model.Build$BuildExecution.cleanUp(Build.java:195)
    at hudson.model.Run.execute(Run.java:1785)
    at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
    at hudson.model.ResourceController.execute(ResourceController.java:98)
    at hudson.model.Executor.run(Executor.java:410)

我不知所措,为什么抱怨丢失的文件,而如果我用Groovy

logger.println(log.getPath());

它将成功打印。

注意:中的变量由通知插件提供,用于直接访问构建日志。loggerPre-send Script

Jenkins file-io groovy jenkins-plugins

评论

0赞 fishi0x01 1/19/2017
是否有可能在 jenkins 主节点上执行构建后操作,而不是在从节点上执行?记录器对象可能在节点之间共享,这就是返回路径的原因,但文件本身可能不存在于主节点上。log.getPath()
0赞 Adri C.S. 2/15/2017
@fishi 事实上,构建后操作似乎是在 Slave 中执行的。我打印了机器而不是创建文件,它报告了主人的。问题仍然是我如何能够从主访问该文件......hostname
0赞 fishi0x01 2/16/2017
一种选择是将文件复制到主服务器。如果使用 Jenkins 管道脚本,则可以使用 stash/unstash。但从问题来看,您似乎没有使用 Jenkins 管道。在这种情况下,您可以查看 Copy to slave 插件(即使名称另有说明,您也可以使用它从 slave 复制到 master)。
0赞 Adri C.S. 2/17/2017
@fishi 你是对的。我没有使用管道,但我会研究一下,看看是否有可能修改作业以采用它。否则,我将采用插件方法。Copy to slave

答:

15赞 Joe M 4/24/2017 #1

在 Jenkins 管道中,不起作用。
您可以改用 readFile,例如:
File log = new File("${WORKSPACE}/${LOG}");

def log = readFile "${WORKSPACE}/${LOG}"

评论

0赞 Adri C.S. 8/3/2017
不。那没有用。正如@MorLajb所建议的那样,它似乎在主节点上运行。
1赞 Ian D. Rossi 12/9/2017
是的,屁股真痛。如果 Pipelines 可以是纯粹的 Groovy,那就更好了。
3赞 Tacahiroy 6/1/2018
是的,这是 Jenkins 的预期行为:issues.jenkins-ci.org/browse/JENKINS-37577
0赞 Prathamesh dhanawade 8/28/2019
我们将如何创建/写入文件?例如,我有一个列表,我想将其写入文件,这很容易通过File.append()完成??
30赞 Pieter Meiresone 5/24/2018 #2

java.io.File方法将引用运行 Jenkins 的主服务器上的文件,而不是从属机器上的当前工作区中的文件(如果此作业确实在从属机器上运行)。

要引用从属计算机上的文件,应使用以下方法readFile

def log = readFile("${WORKSPACE}/${LOG}");

评论

3赞 Jakub Kukul 10/13/2019
旁注:如果 groovy 代码在 Pipeline 中,这将起作用。如果你想从共享库中读取从属文件上的文件,这实际上是不可能的,正如这里所描述的那样 - issues.jenkins-ci.org/browse/JENKINS-56384
0赞 Marco Luly 12/17/2021 #3

我有一个詹金斯工作也有同样的问题。方法对我不起作用,因为我使用了作业 DSL(有一个错误,例如 readFile() 方法没有签名),所以我使用了 readFileFromWorkspace 方法,它对我有用。readFile

您的代码应该像这样修改:

def log = readFileFromWorkspace("${WORKSPACE}/${LOG}");

评论

0赞 Dan Serbyn 9/29/2023
java.lang.NoSuchMethodError:在步骤中找不到此类 DSL 方法“readFileFromWorkspace”