【问题标题】:Jenkins console output not in realtimeJenkins控制台输出不是实时的
【发布时间】:2012-07-22 20:02:38
【问题描述】:

詹金斯很新,我有一个简单但烦人的问题。当我在 Jenkins 上运行作业(构建)时,我触发了 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

【问题讨论】:

  • 您运行的服务器有多强大,执行此脚本需要多长时间?这听起来像是由于服务器过载而导致的延迟。当我的 Jenkins master 满负荷运行时,我也看到了类似的症状。
  • 感谢您的关注,这实际上是有道理的。在这种情况下,我们谈论的是 EC2 实例smallaws.amazon.com/ec2/instance-types,但它只是进程运行。会不会是你需要的更多?
  • 这取决于有多少作业正在运行,但是是的,如果您同时在一个小型实例上运行多个作业,我预计会出现延迟。
  • 我有一个类似的问题,但是,这台机器超出了规格且未充分利用。在jenkins之外运行python脚本也可以按预期实时工作。该作业调用一个python脚本,该脚本跟踪另一个进程的日志文件。日志文件实时更新,jenkins 输出以块的形式转储,就好像它在等待填充缓冲区一样。
  • 嗨 Craig,你说得对,缓冲输出是个问题。使用STDOUT.sync=true 解决了这个问题。

标签: continuous-integration jenkins


【解决方案1】:

澄清一些答案。

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

例如这将等待 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;
    

【讨论】:

    【解决方案2】:

    确保您的脚本正在刷新其标准输出和标准错误。 就我而言,我遇到了与您描述的类似的缓冲问题,但我使用的是 python。 以下python代码为我修复了它:

    import sys
    sys.stdout.flush()
    

    我不是 Ruby 编码员,但 Google 揭示了以下内容:

    $stdout.flush
    

    【讨论】:

    • 嗨,克雷格谢谢你的回答 STDOUT.flush$stdout.flush 会起作用。问题是您需要将许多这些命令放入脚本中,以便在需要时刷新缓冲区。我将发布基本上涵盖同步缓冲区刷新到输出的解决方案。
    • 谢谢,它确实解决了我的问题,因为它在没有flush的shell下运行良好,所以我没有考虑。
    【解决方案3】:

    在我看来python -u 也可以。

    例如在批处理命令中

    python -u foo.py
    

    【讨论】:

      【解决方案4】:

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

      随便写

      STDOUT.sync = true
      

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

      STDOUT.sync = false
      

      这是 Ruby 解决方案。

      【讨论】:

        【解决方案5】:

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

        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:
        

        【讨论】:

          【解决方案6】:

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

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

          [适用于我在 Windows 机器上运行的 Jenkins 1.572。]

          【讨论】:

            【解决方案7】:

            对于某些命令,包括tee,取消缓冲的最佳选择是expect 包中名为unbuffer 的程序。

            用法示例:

            而不是

            somecommand | tee /some/path

            somecommand | unbuffer -p tee /some/path

            来源和更多信息:

            【讨论】:

              【解决方案8】:

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

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

              Jenkins Ruby Plugin

              (可能需要安装)

              【讨论】:

              • 我会试试这个,这需要一些时间。谢谢。
              • 您好,这是行不通的 :( 尝试了相同的结果。另外,由于 ruby​​ 代码保存在 Jenkins 作业中,因此解决方案不是很实用,因此版本控制要困难得多。
              • 我同意该解决方案的“非源代码控制”性质 - 最好在 Jenkins 之外管理任何脚本,然后从工作中调用它。 (对于 Jenkins 中的 shell/batch 块也是如此)
              【解决方案9】:

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

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

              sys.stdout.flush()

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-07-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-02-08
                • 2019-04-11
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多