python-3.x - 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 脚本可以运行清理过程之前被终止。
根据您观察到的症状,了解您如何知道这一点会很有帮助。
无论如何,您发布的 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
可能就足够了。如果上次只创建了前两个,而第三个不存在,没什么大不了的。在适当的地方使用通配符。
推荐阅读
- firebase - 删除旧数据时,以前工作的 Firebase 功能现在失败
- sql - SQL - 在时区
- bash - 将行格式化为 CSV 条目并使用 sed 对其执行转换
- linux - 通过命令提示符加入域:AWS
- java - 在 JDK 11 上运行 Ionic for Android
- docker - Spring Boot v1.5.13 Docker:从请求中获取 Docker IP 而不是客户端 IP
- c++ - 如何正确填充在堆上分配的二维数组?
- regex - Postgres 9.5 中的简单负前瞻不起作用
- python - 如何在 PyQt 中使用 QThreads 在两个方向上设置信号和插槽?
- obfuscation - 编译器为匿名类型生成的类被错误地混淆了