Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
jenkins
提交
63b6e0bc
J
jenkins
项目概览
xxadev
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
63b6e0bc
编写于
12月 12, 2012
作者:
K
Kohsuke Kawaguchi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Added a CLI command to report console output
上级
bac28a5a
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
149 addition
and
0 deletion
+149
-0
changelog.html
changelog.html
+2
-0
core/src/main/java/hudson/cli/ConsoleCommand.java
core/src/main/java/hudson/cli/ConsoleCommand.java
+147
-0
未找到文件。
changelog.html
浏览文件 @
63b6e0bc
...
...
@@ -68,6 +68,8 @@ Upcoming changes</a>
Display class loading statistics in
<code>
/computer/
<i>
name
</i>
/systemInfo
</code>
.
<li
class=
rfe
>
Added
<tt>
list-plugins
</tt>
CLI command.
<li
class=
rfe
>
Added
<tt>
console
</tt>
CLI command that dumps console output from a build.
</ul>
</div>
<!--=TRUNK-END=-->
...
...
core/src/main/java/hudson/cli/ConsoleCommand.java
0 → 100644
浏览文件 @
63b6e0bc
package
hudson.cli
;
import
hudson.Extension
;
import
hudson.console.AnnotatedLargeText
;
import
hudson.model.AbstractBuild
;
import
hudson.model.AbstractProject
;
import
hudson.model.Item
;
import
hudson.model.PermalinkProjectAction.Permalink
;
import
hudson.util.IOUtils
;
import
org.kohsuke.args4j.Argument
;
import
org.kohsuke.args4j.CmdLineException
;
import
org.kohsuke.args4j.Option
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.io.OutputStreamWriter
;
import
java.io.PrintStream
;
/**
* cat/tail/head of the console output.
*
* @author Kohsuke Kawaguchi
*/
@Extension
public
class
ConsoleCommand
extends
CLICommand
{
@Override
public
String
getShortDescription
()
{
return
"Retrieves console output of a build"
;
}
@Argument
(
metaVar
=
"JOB"
,
usage
=
"Name of the job"
,
required
=
true
)
public
AbstractProject
<?,?>
job
;
@Argument
(
metaVar
=
"BUILD"
,
usage
=
"Build number or permalink to point to the build. Defaults to the last build"
,
required
=
false
,
index
=
1
)
public
String
build
=
"lastBuild"
;
@Option
(
name
=
"-f"
,
usage
=
"If the build is in progress, stay around and append console output as it comes, like 'tail -f'"
)
public
boolean
follow
=
false
;
@Option
(
name
=
"-n"
,
metaVar
=
"N"
,
usage
=
"Display the last N lines"
)
public
int
n
=
-
1
;
protected
int
run
()
throws
Exception
{
job
.
checkPermission
(
Item
.
BUILD
);
AbstractBuild
<?,?>
run
;
try
{
int
n
=
Integer
.
parseInt
(
build
);
run
=
job
.
getBuildByNumber
(
n
);
if
(
run
==
null
)
throw
new
CmdLineException
(
"No such build #"
+
n
);
}
catch
(
NumberFormatException
e
)
{
// maybe a permalink?
Permalink
p
=
job
.
getPermalinks
().
get
(
build
);
if
(
p
!=
null
)
{
run
=
(
AbstractBuild
)
p
.
resolve
(
job
);
if
(
run
==
null
)
throw
new
CmdLineException
(
"Permalink "
+
build
+
" produced no build"
);
}
else
{
Permalink
nearest
=
job
.
getPermalinks
().
findNearest
(
build
);
throw
new
CmdLineException
(
String
.
format
(
"Not sure what you meant by \"%s\". Did you mean \"%s\"?"
,
build
,
nearest
.
getId
()));
}
}
OutputStreamWriter
w
=
new
OutputStreamWriter
(
stdout
,
getClientCharset
());
try
{
long
pos
=
n
>=
0
?
seek
(
run
)
:
0
;
if
(
follow
)
{
AnnotatedLargeText
logText
;
do
{
logText
=
run
.
getLogText
();
pos
=
logText
.
writeLogTo
(
pos
,
w
);
}
while
(!
logText
.
isComplete
());
}
else
{
InputStream
in
=
run
.
getLogInputStream
();
IOUtils
.
skip
(
in
,
pos
);
IOUtils
.
copy
(
new
InputStreamReader
(
in
,
run
.
getCharset
()),
w
);
}
}
finally
{
w
.
flush
();
// this pointless flush needed to work around SSHD-154
w
.
close
();
}
return
0
;
}
/**
* Find the byte offset in the log input stream that marks "last N lines".
*/
private
long
seek
(
AbstractBuild
<?,
?>
run
)
throws
IOException
{
class
RingBuffer
{
long
[]
lastNlines
=
new
long
[
n
];
int
ptr
=
0
;
RingBuffer
()
{
for
(
int
i
=
0
;
i
<
n
;
i
++)
lastNlines
[
i
]
=
-
1
;
}
void
add
(
long
pos
)
{
lastNlines
[
ptr
]
=
pos
;
ptr
=
(
ptr
+
1
)%
lastNlines
.
length
;
}
long
get
()
{
long
v
=
lastNlines
[
ptr
];
if
(
v
<
0
)
return
lastNlines
[
0
];
// didn't even wrap around
return
v
;
}
}
RingBuffer
rb
=
new
RingBuffer
();
InputStream
in
=
run
.
getLogInputStream
();
try
{
byte
[]
buf
=
new
byte
[
4096
];
int
len
;
byte
prev
=
0
;
long
pos
=
0
;
boolean
prevIsNL
=
false
;
while
((
len
=
in
.
read
(
buf
))>=
0
)
{
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
byte
ch
=
buf
[
i
];
boolean
isNL
=
ch
==
'\r'
||
ch
==
'\n'
;
if
(!
isNL
&&
prevIsNL
)
rb
.
add
(
pos
);
if
(
isNL
&&
prevIsNL
&&
!(
prev
==
'\r'
&&
ch
==
'\n'
))
rb
.
add
(
pos
);
pos
++;
prev
=
ch
;
prevIsNL
=
isNL
;
}
}
return
rb
.
get
();
}
finally
{
IOUtils
.
closeQuietly
(
in
);
}
}
@Override
protected
void
printUsageSummary
(
PrintStream
stderr
)
{
stderr
.
println
(
"Produces the console output of a specific build to stdout, as if you are doing 'cat build.log'"
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录