通过我自己的插件,我需要知道 Jenkins 节点的工作区中是否存在文件。但是找不到该文件,而该文件确实存在于节点上(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);
结果:
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
我做错了什么?
链接:
最佳答案
您正在将匿名内部类传递给 act(...)
它有一个对其父类的隐式引用,MyBuilder
.我的猜测是即使MyBuilder
工具 Serializable
,由于对另一个不是 Serializable
的对象的引用,它实际上不能被序列化(例如堆栈跟踪指示的 java.io.PrintStream
)。
创建 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.";
}
}
}
然后改用它:
String result = fp.act(new MyFileCallable());
更新: 这是 Java 的 Nested Classes 的链接教程概述了内部类的实例与其封闭的外部类实例之间的关系:
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.
这也在 JLS ( §8.1.3 Inner Classes and Enclosing Instances) 中用更多技术术语进行了解释。
考虑到这一点,这句话来自 Serializable
doc解释你为什么遇到 NotSerializableException
:
When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.
关于java - Jenkins 插件无法访问节点上的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17727054/