简体   繁体   English

Jenkins 插件无法访问节点上的文件

[英]Jenkins plugin can't access file on node

Through my own plugin, I need to know about the existence of a file in the workspace of a Jenkins node.通过我自己的插件,我需要知道一个 Jenkins 节点的工作区中文件的存在。 But the file can't be found whereas it really exists on the node ( D:\\workspace\\JOB_NAME\\test.txt ).但是无法找到该文件,而它确实存在于节点 ( D:\\workspace\\JOB_NAME\\test.txt ) 上。

public class MyBuilder extends Builder implements Serializable {

    private static final long serialVersionUID = 1L;
    
    public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) 
            throws InterruptedException, IOException {
            
        FilePath fp = new FilePath(build.getWorkspace(), "test.txt");

        String result = fp.act(new FileCallable<String>() {
            private static final long serialVersionUID = 1L;

            @Override
            public String invoke(File file, VirtualChannel channel) throws IOException, InterruptedException {
                if (file.getAbsoluteFile().exists()){
                    return file.getName() + " exists.";
                } else {
                    return file.getName() + " doesn't exist.";
                }
            }
        });

        System.out.println("result: " + result);

Result:结果:

FATAL: remote file operation failed: D:\workspace\JOB_NAME\test.txt at hudson.remoting.Channel@182752b:Node
hudson.util.IOException2: remote file operation failed: D:\workspace\JOB_NAME\test.txt at hudson.remoting.Channel@182752b:Node
    at hudson.FilePath.act(FilePath.java:900)
    at hudson.FilePath.act(FilePath.java:877)
    at com.company.tlb.proj.MyBuilder.perform(Unknown Source)
    at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:19)
    at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:804)
    at hudson.model.Build$BuildExecution.build(Build.java:199)
    at hudson.model.Build$BuildExecution.doRun(Build.java:160)
    at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:586)
    at hudson.model.Run.execute(Run.java:1575)
    at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:46)
    at hudson.model.ResourceController.execute(ResourceController.java:88)
    at hudson.model.Executor.run(Executor.java:237)
Caused by: java.io.IOException: Unable to serialize hudson.FilePath$FileCallableWrapper@18b91cb
    at hudson.remoting.UserRequest.serialize(UserRequest.java:166)
    at hudson.remoting.UserRequest.<init>(UserRequest.java:62)
    at hudson.remoting.Channel.call(Channel.java:671)
    at hudson.FilePath.act(FilePath.java:893)
    ... 11 more
Caused by: java.io.NotSerializableException: java.io.PrintStream
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
    at hudson.remoting.UserRequest._serialize(UserRequest.java:155)
    at hudson.remoting.UserRequest.serialize(UserRequest.java:164)
    ... 14 more

What am I doing wrong?我究竟做错了什么?

Links:链接:

You're passing an anonymous inner-class to act(...) which has an implicit reference to its parent class, MyBuilder .您将匿名内部类传递给act(...) ,它隐式引用其父类MyBuilder My guess is that even though MyBuilder implements Serializable , it can't actually be serialized due to some reference to another object that isn't Serializable (eg a java.io.PrintStream as the stack-trace indicates).我的猜测是,即使MyBuilder实现了Serializable ,由于对另一个不可Serializable对象的引用(例如堆栈跟踪指示的java.io.PrintStream ,它实际上无法序列化。

Make your instance of FileCallable<String> a static inner class to get rid of the implicit reference to its parent:使您的FileCallable<String>实例成为静态内部类,以摆脱对其父级的隐式引用:

private static class MyFileCallable implements FileCallable<String> {
  private static final long serialVersionUID = 1L;
  @Override
  public String invoke(File file, VirtualChannel channel) throws IOException, InterruptedException {
    if (file.getAbsoluteFile().exists()){
      return file.getName() + " exists.";
    } else {
      return file.getName() + " doesn't exist.";
    }
  }
}

And then use that instead:然后改用它:

String result = fp.act(new MyFileCallable());

Update: Here's a link to Java's Nested Classes tutorial which outlines the relationship between an instance of an inner class an its enclosing outer class instance:更新:这是 Java 的 嵌套类教程的链接,它概述了内部类的实例与其封闭的外部类实例之间的关系:

An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance. InnerClass 的实例只能存在于 OuterClass 的实例中,并且可以直接访问其封闭实例的方法和字段。

This is also explained in more technical terms in the JLS ( §8.1.3 Inner Classes and Enclosing Instances ).这也在 JLS(第8.1.3 节内部类和封闭实例中用更多技术术语进行了解释。

With that in mind, this quote from the Serializable doc explains why you encountered the NotSerializableException :考虑到这一点,来自Serializable文档的这句话解释了您遇到NotSerializableException

When traversing a graph, an object may be encountered that does not support the Serializable interface.遍历图时,可能会遇到不支持Serializable接口的对象。 In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.在这种情况下,将抛出 NotSerializableException 并标识不可序列化对象的类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM