[英]Jenkins CI Plugin run on slave
我正在為 Jenkins CI 開發一個插件。 現在當插件在從機上運行時出現問題。 在從站上,我需要登錄到主站,從主站傳遞參數並在從站上啟動進程。 因此我寫了這段代碼:
private static class LauncherCallable implements FilePath.FileCallable<String>
{
private BuildListener listener;
private SetupConfig config;
private String nsisVersion;
private Launcher launcher;
public LauncherCallable(BuildListener listener, SetupConfig config, String nsisVersion, Launcher launcher)
{
this.listener = listener;
this.config = config;
this.nsisVersion = nsisVersion;
this.launcher = launcher;
}
@Override
public String invoke(File file, VirtualChannel vc) throws IOException, InterruptedException
{
try
{
final RemoteOutputStream ros = new RemoteOutputStream(listener.getLogger());
ScriptGenerator scriptGenerator = new ScriptGenerator(config);
listener.getLogger().println("Downloading NSIS...");
String nsisPath = Downloader.getNsisPath(listener, nsisVersion);
listener.getLogger().println("Derteming version from AssembyInfo...");
String assemblyVersion = AssemblyVersionParser.determineVersion(new File(file + "/" + config.getAssemblyInfoPath()));
listener.getLogger().println(" -> Version: " + assemblyVersion);
listener.getLogger().println("Generating .nsi file...");
String nsiString = scriptGenerator.generateScript();
nsiString = nsiString.replace("$VERSION", assemblyVersion);
listener.getLogger().println("Checking NSIS installation...");
File nsisExecutable = new File(new File(nsisPath).getAbsolutePath() + "/makensis.exe");
if (!nsisExecutable.exists())
throw new Exception("Could not find NSIS executable: " + nsisExecutable);
listener.getLogger().println("Writing .nsi file...");
String scriptGuid = UUID.randomUUID().toString();
File scriptFile = new File(file + "/" + scriptGuid + ".nsi");
PrintStream scriptOutStream = new PrintStream(new FileOutputStream(scriptFile, false));
scriptOutStream.print(nsiString);
scriptOutStream.close();
listener.getLogger().println("Launching NSIS...");
ProcStarter ps = launcher.new ProcStarter();
ArgumentListBuilder command = new ArgumentListBuilder();
command.addTokenized(nsisExecutable.toString() + " " + scriptFile.getAbsolutePath());
ps.cmds(command); //.stdout(listener)
Proc proc = launcher.launch(ps);
int nsisReturn = proc.join();
listener.getLogger().println("NSIS returned: " + nsisReturn);
listener.getLogger().println("Deleting temp file...");
if (!scriptFile.delete())
throw new Exception("Could not delete script file " + scriptFile.getAbsolutePath() + " !");
return (nsisReturn == 0) ? "SUCCESS" : "FAIL";
} catch (Exception ex)
{
ex.printStackTrace();
ex.printStackTrace(listener.getLogger());
return "FAIL";
}
}
@Override
public void checkRoles(RoleChecker rc) throws SecurityException
{
}
}
可調用對象由主服務器插件中的以下代碼運行:
build.getWorkspace().act(fc);
通過這樣做,我得到以下異常:
java.io.IOException: remote file operation failed: C:\\[...] at hudson.remoting.Channel@4cf8aa7c:CIAgent:
java.io.IOException: Unable to serialize hudson.FilePath$FileCallableWrapper@3b712782
at hudson.FilePath.act(FilePath.java:987)
at hudson.FilePath.act(FilePath.java:969)
at jenkinsnsis.JenkinsNsisPlugin.NsisPlugin.perform(NsisPlugin.java:136)
at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20)
at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:779)
at hudson.model.Build$BuildExecution.build(Build.java:205)
at hudson.model.Build$BuildExecution.doRun(Build.java:162)
at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:537)
at hudson.model.Run.execute(Run.java:1741)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
at hudson.model.ResourceController.execute(ResourceController.java:98)
at hudson.model.Executor.run(Executor.java:408)
Caused by: java.io.IOException: Unable to serialize hudson.FilePath$FileCallableWrapper@3b712782
at hudson.remoting.UserRequest.serialize(UserRequest.java:169)
at hudson.remoting.UserRequest.<init>(UserRequest.java:63)
at hudson.remoting.Channel.call(Channel.java:776)
at hudson.FilePath.act(FilePath.java:980)
... 11 more
Caused by: java.io.NotSerializableException: hudson.Launcher$RemoteLauncher
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
...
我究竟做錯了什么? 不幸的是,我沒有找到任何使用日志和啟動過程的例子。 謝謝!
為了將FileCallable
對象傳遞到遠程機器,Jenkins 需要能夠序列化整個對象。 這意味着所有字段都需要實現java.io.Serializable
。
在這種情況下,我猜您的SetupConfig
類型是不可序列化的。
如果您擁有此類型並且可以將其標記為Serializable
,並確保其所有字段都可以序列化,那么應該可以解決它。 如果這是第三方類,您可能需要在invoke
方法中構造SetupConfig
實例。
編輯:既然您已經發布了完整的java.io.NotSerializableException: hudson.Launcher$RemoteLauncher
,我們可以看到實際上Launcher
是無法序列化的類( java.io.NotSerializableException: hudson.Launcher$RemoteLauncher
)。
您不需要將Launcher
傳遞給您的可調用對象——您可以像剛才一樣使用ArgumentListBuilder
,但您可以使用ProcessBuilder
而不是ProcStarter
來執行 NSIS。
( invoke
方法中的所有內容invoke
在遠程機器上運行,因此您無需執行任何特殊操作)。
例如:
ArgumentListBuilder args = ...;
ProcessBuilder proc = new ProcessBuilder(args.toList());
proc.start().waitFor();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.