Jenkins控制台输出不是实时的

时间:2012-07-24 13:30:20

标签: continuous-integration jenkins

詹金斯很新,我有一个简单但烦人的问题。当我在Jenkins上运行作业(Build)时,我正在触发ruby命令来执行我的测试脚本。

问题是Jenkins没有从控制台实时显示输出。这是触发日志。

Building in workspace /var/lib/jenkins/workspace/foo_bar
No emails were triggered.
[foo_bar] $ /bin/sh -xe /tmp/hudson4042436272524123595.sh
+ ruby /var/lib/jenkins/test-script.rb

基本上它会挂起此输出,直到构建完成,而不是显示完整输出。有趣的是,这不是一致的行为,有时它的工作原理应该如此。但大多数时候没有实时的控制台输出。

Jenkins版本:1.461

9 个答案:

答案 0 :(得分:47)

澄清一些答案。

  • rubypython或任何合理的脚本语言都会缓冲输出;这是为了最小化IO;写入磁盘很慢,写入控制台很慢......
  • 通常,在缓冲区中有足够的数据并对换行符进行特殊处理后,数据会自动获得flush()。例如写一个没有换行符的字符串然后sleep()sleep()完成之后才会写任何内容(我只使用sleep作为示例,随意替换任何其他昂贵的系统调用)。

e.g。这将等待8秒,打印一行,再等5秒,打印第二行。

from time import sleep

def test():
    print "ok",
    time.sleep(3)
    print "now",
    time.sleep(5)
    print "done"
    time.sleep(5)
    print "again"

test()
  • rubySTDOUT.sync = true,打开autoflush;对STDOUT的所有写入后跟flush()。这可以解决您的问题,但会产生更多的IO。

    STDOUT.sync = true
    
  • 对于python,您可以使用python -u或环境变量PYTHONUNBUFFERED使stdin/stdout/stout无法缓冲,但there are other solutions不会更改stdinstderr

    export PYTHONUNBUFFERED=1
    
  • perl,您有autoflush

    autoflush STDOUT 1;
    

答案 1 :(得分:10)

确保你的脚本正在刷新stdout,stderr。 在我的情况下,我有一个类似于你描述的抛光问题,但我使用的是python。 python下面的代码为我修复了它:

import sys
sys.stdout.flush()

我不是Ruby代码,但谷歌揭示了以下内容:

$stdout.flush

答案 2 :(得分:5)

在我看来python -u也可以。

E.g。在批处理命令

python -u foo.py

答案 3 :(得分:4)

这里最简单的解决方案是打开同步缓冲区输出。 @Craig在他的回答中写到的东西,但是一行解决方案将覆盖整个脚本,并且不需要你多次刷新缓冲区。

只需写下

STDOUT.sync = true

背后的逻辑很简单,为避免使用IO操作多次缓冲输出。要禁用此功能

STDOUT.sync = false

这是Ruby解决方案。

答案 4 :(得分:3)

其他每个答案都针对一个或另一个程序,但我在这里找到了更通用的解决方案:

https://unix.stackexchange.com/a/25378

您可以使用stdbuf来改变任何程序的缓冲行为。

在我的情况下,我通过teegrep来管道输出来自shell脚本,以将行拆分为控制台或基于内容的文件。如OP所述,控制台正在悬挂。这解决了它:

./slowly_parse.py login.csv |tee >(grep -v LOG: > out.csv) | stdbuf -oL -eL grep LOG:

最终我发现我可以将--line-buffered传递给grep以获得相同的结果:

./slowly_parse.py login.csv |tee >(grep -v LOG: > out.csv) | grep --line-buffered LOG:

答案 5 :(得分:1)

其他答案是正确的,说您需要确保标准输出不被缓冲。

另一件需要注意的事情是Jenkins本身会逐行缓冲。如果您有一个缓慢运行的进程,它会发出单个字符(例如,为成功测试打印.的nunit测试套件摘要,并为错误打印E),您将看不到任何内容行尾。

[我的Jenkins 1.572运行在Windows机箱上。]

答案 6 :(得分:1)

对于某些命令,包括tee,最好的解缓冲选择是来自unbuffer程序包的名为expect的程序。

用法示例:

代替

somecommand | tee /some/path

somecommand | unbuffer -p tee /some/path

来源和更多信息:

答案 7 :(得分:0)

操作系统本质上是缓冲输出数据,以节省CPU,Jenkins也是如此。

看起来您正在使用shell命令来运行Ruby脚本 -
我建议直接通过专用插件运行你的Ruby脚本:

Jenkins Ruby Plugin

(可能需要安装)

答案 8 :(得分:0)

Python会缓冲其输出轨迹,并在脚本末尾打印它,以最大程度地减少在控制台上的写入,因为写入控制台的速度很慢。

跟踪后可以使用以下命令。它将所有跟踪刷新到控制台,该跟踪在该命令之前排队。

  

sys.stdout.flush()