首页 > 解决方案 > 有没有办法让詹金斯在 X 分钟内不记录任何内容的阶段失败?

问题描述

我有一个 Jenkins Pipeline,它并行运行多个阶段。

我正在寻找一种方法来单独记录每个阶段(有点像在 Blue Ocean 中)并监视阶段日志以查看它是否被卡住。有时我们的脚本会卡住,或者其他 java/groovy 代码正在运行并保持卡住而不必抛出异常。

因此,如果某个阶段在 10 分钟内没有记录,我需要失败。我试图找到是否有办法以编程方式实时监控控制台日志,但我找不到。

我正在考虑让每个阶段也记录到一个文件并检查该文件的“lastModifiedDate”。所以我去做了tee这样的事情:

stage('Test') {
  steps {
    script {
      tee ("${WORKSPACE}/logs/${STAGE_NAME}.log"){
        echo "TEST"
        sleep(15)
        echo "Done"
      }
    }
  }
}

这有效并创建了一个日志文件。现在我想轮询该目录并检查文件是否已被修改,否则将失败。为此,我使用了一些基于 Java 的 Watch Service 的 Groovy 代码(在https://docs.oracle.com/javase/tutorial/essential/io/notification.html中有更深入的文档):

private void watchDirectory(String directoryToWatch) {
    Path path = Paths.get(directoryToWatch)
    WatchService watchService = FileSystems.getDefault().newWatchService()
    boolean poll = true
    boolean failed = false
    long lastModified = System.currentTimeMillis()
    while (poll) {
        WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY)
        for (WatchEvent<?> event : key.pollEvents()) {
            Path changed = (Path) event.context()
            if (changed.endsWith("${STAGE_NAME}.log")) {
                println("My file has changed")
                lastModified = System.currentTimeMillis()
            }
        }

        if (System.currentTimeMillis() - lastModified > 20000) {
            println("20 seconds")
            watchService.close()
            failed = true
            break
        }
        poll = key.reset();
    }

    if (failed) {
        catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
            sh "exit 1"
        }
    }
}

这个 groovy 代码在我的本地机器上工作,但在 Jenkins 中使用会引发异常line 8: WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY):

java.nio.file.NoSuchFileException: /data/jenkins/workspace/build_name/logs
  at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
  at sun.nio.fs.UnixException.asIOException(UnixException.java:111)
  at sun.nio.fs.LinuxWatchService$Poller.implRegister(LinuxWatchService.java:246)
  at sun.nio.fs.AbstractPoller.processRequests(AbstractPoller.java:260)
  at sun.nio.fs.LinuxWatchService$Poller.run(LinuxWatchService.java:329)
  at java.lang.Thread.run(Thread.java:745)

在我看来,它无法通过 Jenkins 自定义 Groovy 解释器来实现。或者,也许我做错了什么。

那么,如果有的话,是否有更好的解决方案来实现这一目标?

标签: javajenkinsgroovyjenkins-pipeline

解决方案


推荐阅读