首页 > 解决方案 > Jenkins:构建取消后,在 Python 脚本中处理 SIGTERM 中断,以便在完成之前进行清理

问题描述

我的 Jenkins 服务器(版本 2.167)正在运行一个 shell 构建作业,该作业执行使用 Python 3.7.0 编写的脚本。

有时用户需要手动取消构建(通过单击 Jenkins GUI 中带有白色十字的红色按钮),Python 脚本需要处理中断以便在退出前执行清理任务。有时,中断被正确处理,但其他时候,似乎父进程在 Python 脚本可以运行清理过程之前被终止。

在 Python 脚本的开头,我定义了以下内容:

def cleanup_after_int(signum, frame):
    # some cleanup code here
    sys.exit(0)

signal.signal(signal.SIGINT, cleanup_after_int)
signal.signal(signal.SIGTERM, cleanup_after_int)

# the rest of the script here

我使用的代码是否足够,还是应该考虑更多?

用于中止构建的 Jenkins 文档是https://wiki.jenkins.io/display/JENKINS/Aborting+a+build

找到了一个很好的文档来展示它是如何工作的:https ://gist.github.com/datagrok/dfe9604cb907523f4a2f

标签: python-3.xjenkins

解决方案


你描述一个种族:

似乎父进程 [有时] 在 Python 脚本可以运行清理过程之前被终止。

根据您观察到的症状,了解您如何知道这一点会很有帮助。

无论如何,您发布的 python 代码看起来不错。如果将SIGTERM 传递到您的 python 进程,它应该按预期工作。也许詹金斯只是终止了父 bash。或者也许 bash 和 python 都在同一个进程组中,并且 jenkins 向进程组发出信号。注意ps -j输出中的PGRP。

也许您的清理代码很复杂,并且需要的资源并不总是可用的。例如,可能stdout是到父级的管道,并且清理代码记录到该打开的文件描述符,尽管有时死去的父级已将其关闭。

您可能会考虑使用第 3 章调用: http ://man7.org/linux/man-pages/man3/daemon.3.html 首先“守护”清理代码。然后,您的清理工作至少会不那么激烈,从而在您测试它以及在生产中使用它时产生更多可重现的结果。

您可以选择让父 bash 脚本编排清理:

trap "python cleanup.py" SIGINT SIGTERM
python doit.py

您可以选择完全不担心退出时的清洁。相反,记录你弄脏的任何东西,并在开始之前(同步地)清理它,然后开始你定期安排的脚本来完成真正的工作。假设您创建了三个临时文件,并希望整理它们。/tmp/temp_files.txt在创建每个名称之前将每个名称附加到。确保刷新缓冲区并使用fsync()或持久化写入close()

您可以选择在启动时清理而不记录日志,而不是记录。例如:

$ rm -f /tmp/{1,2,3}.txt

可能就足够了。如果上次只创建了前两个,而第三个不存在,没什么大不了的。在适当的地方使用通配符。


推荐阅读