输出我的作业正在运行的 Jenkins 作业的控制台文本 [英] Output the console text of a Jenkins job that my Job is running
问题描述
I tried looking here and here and here.
我正在使用 dsl 流程.而且我希望能够看到从我正在运行的作业中构建的作业打印出来的控制台日志.我尝试四处寻找示例,但似乎找不到我要找的东西.如果这个问题没有使用正确的术语或以不同的方式提出,我深表歉意.我只想找到如何做到这一点的答案.
I am using the dsl flow. And I would like to be able to see the console log printed out of the job i'm building within the job I'm running. I tried looking around for examples and I couldn't seem to find what I was looking for. I apologize if this question is not using the correct terminology or that it's been asked in different ways. I just want to find the answer of how to do this.
A = build("Main Suites", SUITE: "qa_smoketests", OS: "mac")
下面我尝试这样做,但似乎没有用
below I tried to do this but it didn't seem to work
OUTPUT = A.build.doConsoleText()
out.println(OUTPUT)
更新:
我尝试了第二种方法来动态更新它,但我的 url 一直有问题?奇怪的是,如果我单击错误中的 url 链接,它会将我带到相应的页面.我确实必须修改东西 b/c 作业名称中有空格.我还为这篇文章编辑了我的错误日志,用 MYHOSTURL 而不是我实际的 Jenkins 主机 URL.
I tried the 2nd method to update it on the fly and I keep getting an issue with the url? strangely if I click the url link in the error it takes me to the appropriate page. I did have to modify things b/c the Job name has spaces in it. I also edited my error log for this post to say MYHOSTURL instead of my actual Jenkins host url.
ERROR: Failed to run DSL Script
java.util.concurrent.ExecutionException: org.codehaus.groovy.runtime.InvokerInvocationException: java.io.IOException: Server returned HTTP response code: 401 for URL: http://MYHOSTURL/job/Main%20Suites/159/consoleText
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:188)
at java_util_concurrent_Future$get$7.call(Unknown Source)
at com.cloudbees.plugins.flow.FlowDelegate$_parallel_closure6.doCall(FlowDSL.groovy:440)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at groovy.lang.Closure.call(Closure.java:415)
at groovy.lang.Closure.call(Closure.java:428)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1379)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1351)
at org.codehaus.groovy.runtime.dgm$170.invoke(Unknown Source)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at com.cloudbees.plugins.flow.FlowDelegate.parallel(FlowDSL.groovy:438)
at sun.reflect.GeneratedMethodAccessor10240.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1079)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:723)
at com.cloudbees.plugins.flow.FlowDelegate.invokeMethod(FlowDSL.groovy)
at hudson.util.spring.ClosureScript.invokeMethod(ClosureScript.java:83)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:72)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
at Script1.run(Script1.groovy:12)
at Script1$run.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at Script1$run.call(Unknown Source)
at com.cloudbees.plugins.flow.FlowDSL.executeFlowScript(FlowDSL.groovy:84)
at com.cloudbees.plugins.flow.FlowRun$FlyweightTaskRunnerImpl.run(FlowRun.java:219)
at hudson.model.Run.execute(Run.java:1759)
at com.cloudbees.plugins.flow.FlowRun.run(FlowRun.java:155)
at hudson.model.ResourceController.execute(ResourceController.java:89)
at hudson.model.Executor.run(Executor.java:240)
at hudson.model.OneOffExecutor.run(OneOffExecutor.java:43)
Caused by: org.codehaus.groovy.runtime.InvokerInvocationException: java.io.IOException: Server returned HTTP response code: 401 for URL: http://MYHOSTURL/job/Main%20Suites/159/consoleText
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:97)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at groovy.lang.Closure.call(Closure.java:415)
at groovy.lang.Closure.call(Closure.java:409)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.IOException: Server returned HTTP response code: 401 for URL: http://MYHOSTURL/job/Main%20Suites/159/consoleText
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1627)
at sun.net.www.protocol.http.HttpURLConnection$getInputStream.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
at Script1.responseFrom(Script1.groovy:82)
at Script1$responseFrom.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at Script1.printConsoleOutputTextChunksFrom(Script1.groovy:62)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:361)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
at Script1$_run_closure2.doCall(Script1.groovy:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at Script1$_run_closure2.doCall(Script1.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
at com.cloudbees.plugins.flow.FlowDelegate$_parallel_closure5_closure7.doCall(FlowDSL.groovy:427)
at sun.reflect.GeneratedMethodAccessor8673.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:903)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at com.cloudbees.plugins.flow.FlowDelegate$_parallel_closure5_closure7.doCall(FlowDSL.groovy)
at sun.reflect.GeneratedMethodAccessor8672.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
... 9 more
}
Finished: FAILURE
更新 2:
所以我能够通过修改 responseFrom 函数来处理需要身份验证的页面,从而使第一种方法起作用.
So I was able to get the first method working by modifying the responseFrom function to handle a page that needs authentication.
InputStream responseFrom(String url)
{
// See Using java.net.URLConnection to fire and handle HTTP requests
// https://stackoverflow.com/a/2793153/1744774
URL myURL = new URL(url);
HttpURLConnection connection = (HttpURLConnection)myURL.openConnection();
String userCredentials = "username:password";
String encoding = new sun.misc.BASE64Encoder().encode(userCredentials.getBytes());
String basicAuth = "Basic " + encoding;
connection.setRequestProperty("Authorization", basicAuth);
connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
return connection.getInputStream();
}
但是,我仍然无法让第二种方法起作用.我猜它与用于从下游作业获取内部版本号的函数有关.
However I'm still having issues getting the 2nd method to work. I guess it's with the function that is being used to get the build number from the downstream job.
java.util.concurrent.ExecutionException:org.codehaus.groovy.runtime.InvokerInvocationException:groovy.lang.MissingMethodException:没有方法签名:静态java.lang.Integer.parseUnsignedInt() 适用于参数类型:(java.lang.String) 值:[164]
java.util.concurrent.ExecutionException: org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: static java.lang.Integer.parseUnsignedInt() is applicable for argument types: (java.lang.String) values: [164]
推荐答案
有趣的问题.我无法理解反对票.
Interesting question. I can't comprehend the downvote.
- 您的第一个链接描述了您应该如何做到这一点:通过重复的 GET 请求".
- 第二个是关于根据下游作业的控制台输出的内容设置上游作业的结果.这可以通过其他方法更容易实现,但解析控制台输出.
- 第三个是相反的方向:将输出从上游作业传递到下游作业.
我将尝试第一个,然后会相应地更新此答案.
I'm going to try the first and will update this answer accordingly then.
一旦下游构建完成,以下更新上游的日志.
The following updates the upstream's log once the downstream build has finished.
// From: Output the console text of a Jenkins job that my Job is running
// http://stackoverflow.com/a/31573477/1744774
final String JENKINS_HOST = 'http://<your Jenkins host>'
final String DOWNSTREAM_NAME = '<your downstream job's name>'
final String SEPARATOR = new String(new char[8]).replace(' ', '-')
final int DOWNSTREAM_BUILD_NO = build(DOWNSTREAM_NAME).getBuild().getNumber()
println("${SEPARATOR} Begin console HTML output of ${DOWNSTREAM_NAME} #${DOWNSTREAM_BUILD_NO} ${SEPARATOR}")
printConsoleOutputHtmlFrom(
"${JENKINS_HOST}/job/${DOWNSTREAM_NAME}/${DOWNSTREAM_BUILD_NO}/console")
println("${SEPARATOR} Begin console text output of ${DOWNSTREAM_NAME} #${DOWNSTREAM_BUILD_NO} ${SEPARATOR}")
printConsoleOutputTextFrom(
"${JENKINS_HOST}/job/${DOWNSTREAM_NAME}/${DOWNSTREAM_BUILD_NO}/consoleText")
println("${SEPARATOR} End console output of ${DOWNSTREAM_NAME} ${SEPARATOR}")
import org.xml.sax.InputSource
void printConsoleOutputHtmlFrom(String consoleUrl)
{
println(xPathExpression('//pre[contains(@class, "console-output")]')
.evaluate(new InputSource(responseFrom(consoleUrl))))
}
import java.nio.charset.StandardCharsets
void printConsoleOutputTextFrom(String consoleTextUrl)
{
BufferedReader log = new BufferedReader(
new InputStreamReader(responseFrom(consoleTextUrl), StandardCharsets.UTF_8.name()));
while ((line = log.readLine()) != null)
{
println(line)
}
}
InputStream responseFrom(String url)
{
// See Using java.net.URLConnection to fire and handle HTTP requests
// http://stackoverflow.com/a/2793153/1744774
URLConnection connection = new URL(url).openConnection();
connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
return connection.getInputStream();
}
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
XPathExpression xPathExpression(String expression)
{
// See How to read XML using XPath in Java
// http://stackoverflow.com/a/2811101/1744774
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
return xPath.compile(expression);
}
参考文献:
- 构建流程插件
- com.cloudbees.plugins.flow.JobInvocation(由
build()
返回) - hudson.model.Run(由
返回JobInvocation.getBuild()
)
- Build Flow Plugin
- com.cloudbees.plugins.flow.JobInvocation (returned by
build()
) - hudson.model.Run (returned by
JobInvocation.getBuild()
)
以下内容会即时更新上游的日志.
The following updates the upstream's log on the fly.
// From: Output the console text of a Jenkins job that my Job is running
// http://stackoverflow.com/a/31573477/1744774
final String JENKINS_HOST = 'http://<your Jenkins host>'
final String DOWNSTREAM_NAME = '<your downstream job's name>'
final String SEPARATOR = new String(new char[8]).replace(' ', '-')
import java.util.concurrent.TimeUnit
parallel(
{ build(DOWNSTREAM_NAME) },
{
final String THIS_BUILD_NAME = build.getProject().getName()
final int THIS_BUILD_NO = build.getNumber()
final int DOWNSTREAM_BUILD_NO = downstreamBuildNoFrom(
"${JENKINS_HOST}/job/${THIS_BUILD_NAME}/${THIS_BUILD_NO}/consoleText")
println("${SEPARATOR} Begin console output of ${DOWNSTREAM_NAME} #${DOWNSTREAM_BUILD_NO} ${SEPARATOR}")
printConsoleOutputTextChunksFrom(
"${JENKINS_HOST}/job/${DOWNSTREAM_NAME}/${DOWNSTREAM_BUILD_NO}/consoleText", 3L, TimeUnit.SECONDS)
println("${SEPARATOR} End console output of ${DOWNSTREAM_NAME} #${DOWNSTREAM_BUILD_NO} ${SEPARATOR}")
})
int downstreamBuildNoFrom(String thisBuildConsoleTextUrl)
{
int downstreamBuildNo = -1
while (downstreamBuildNo <= 0)
{
TimeUnit.SECONDS.sleep(1L)
BufferedReader log = new BufferedReader(
new InputStreamReader(responseFrom(thisBuildConsoleTextUrl), StandardCharsets.UTF_8.name()));
while ((line = log.readLine()) != null)
{
if (line.matches('.* Build .* started'))
{
final int buildNoIdx = line.indexOf('#') + 1
downstreamBuildNo = Integer.parseUnsignedInt(
line.substring(buildNoIdx, line.indexOf(' ', buildNoIdx)))
break
}
/*if (log.lines().anyMatch(t -> t.matches(".* Build .* started")))
{
// in case of Java >=8
}*/
}
}
return downstreamBuildNo
} // downstreamBuildNoFrom()
import java.nio.charset.StandardCharsets
void printConsoleOutputTextChunksFrom(String consoleTextUrl, long updateInterval, TimeUnit updateIntervalUnit)
{
final int LINE_BREAK_LENGTH = System.getProperty("line.separator").length()
int charsPrintedSoFar = 0
while (true) // effectively a do { ... }
{
int charsPrintedThisTime = 0
BufferedReader chunk = new BufferedReader(
new InputStreamReader(responseFrom(consoleTextUrl), StandardCharsets.UTF_8.name()))
chunk.skip(charsPrintedSoFar)
while ((line = chunk.readLine()) != null)
{
println(line)
charsPrintedThisTime = line.length() + LINE_BREAK_LENGTH
charsPrintedSoFar += charsPrintedThisTime
}
updateIntervalUnit.sleep(updateInterval)
if (charsPrintedThisTime == 0)
break
}
} // printConsoleOutputTextChunksFrom()
InputStream responseFrom(String url)
{
// See Using java.net.URLConnection to fire and handle HTTP requests
// http://stackoverflow.com/a/2793153/1744774
URLConnection connection = new URL(url).openConnection();
connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
return connection.getInputStream();
}
这篇关于输出我的作业正在运行的 Jenkins 作业的控制台文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!