在Jenkins作业中止时在Python中运行清理函数
我写了一个Python脚本,这个脚本运行了一段时间,并在正常结束时会进行清理,比如:
import time
def cleanUp():
#delete some temporary files and so on
print("Clean up done")
if __name__=="__main__":
startTime = time.time()
while time.time() - startTime < 60:
# Performing some commands
print("Still running")
cleanUp()
我把这段代码作为Jenkins的一个任务在运行。为了确保无论如何都能进行清理,也就是说即使我中止了Jenkins的任务,我也用了signal.signal这个功能。经过研究发现,Jenkins在终止一个任务时会发送一个“TERM”信号(具体可以查看这个链接:https://gist.github.com/datagrok/dfe9604cb907523f4a2f)。因此,我添加了以下代码,并且加了一个控制机制来检查它是否有效,因为Jenkins在停止任务后不会显示剩下的日志(会立即显示“ABORTED”,见链接):
import time
import signal
pythonObj = None
def cleanUp():
# object that I defined globally, reconstructing it in a separate script is quite cumbersome
global pythonObj
#delete some temporary files and so on
print("Clean up done")
# Write some text to a file, to see if this part was actually run
with open(r"C:\temp\abx.txt", 'w') as file:
file.write("Process has been finished prematurely")
signal.signal(signal.SIGTERM, cleanUp)
if __name__=="__main__":
startTime = time.time()
while time.time() - startTime < 60:
# Creation of python object
pythonObj = someFunct()
print("Still running")
cleanUp()
可惜的是,我在运行Jenkins任务的电脑的C:\temp目录下找不到“控制”文件。
我的问题:使用 signal.signal(signal.SIGTERM, cleanUp)
这种方式是否合适(还是应该用别的方式)?或者我在使用signal.signal时犯了错误?
我也尝试过用 atexit
来注册cleanUp,但这也没有给我想要的结果。
编辑 1:我没有提到的一点是,我需要将一些复杂的输入传递给cleanUp函数。我已经考虑过在管道中使用构建后的操作。
编辑 2:如下面提到的,理论上可以将输入传递过去以重建对象。然而,这个重建过程相当麻烦,因为我只想快速清理,如果需要重建整个过程,那就不可能了,所以我尽量避免这个选项。
非常感谢!
1 个回答
一个合适的方法是使用内置的功能——Jenkinsfile 语法中有一个专门为你的需求设计的块:
来自 Pipeline 语法:
post
部分定义了一些额外的步骤,这些步骤会在 Pipeline 或某个阶段完成后运行(具体取决于post
部分在 Pipeline 中的位置)。post
可以支持以下任意的后置条件块:always
(总是)、changed
(变化)、fixed
(修复)、regression
(回归)、aborted
(中止)、failure
(失败)、success
(成功)、unstable
(不稳定)、unsuccessful
(不成功)和cleanup
(清理)。这些条件块允许根据 Pipeline 或阶段的完成状态在每个条件内执行步骤。条件块的执行顺序如下所示。
// Jenkinsfile
def arg1 = 'one'
def arg2
pipeline {
// ...
stages {
stage('Some build logic') {
steps {
script {
arg2 = 'two'
env.ARG3 = 'three'
}
// build steps
}
}
}
post {
aborted {
sh "python3 cleanup.py $arg1 $arg2"
}
}
}
根据你的目标,你可以选择任何后置条件来使用,也可以将它们组合在一起。
我需要将一些输入传递给 cleanUp 函数
在你的例子中,cleanUp()
不接受任何参数。不过,aborted
、cleanup
或其他任何 post
块的语法和任何 stage
中的 steps
是一样的:
这意味着你对变量有相同的控制权——你可以在之前的阶段中设置它们,并在你的函数中使用。注意将单引号改为双引号,以启用 Groovy 字符串插值。