Reputation: 126
I wrote a script in Python that is running for some time and performing a clean up as soon as it terminates regularly like:
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()
I'm running this code as a Jenkins job. In order to clean up no matter what, i.e. also when I abort the Jenkins job, I used signal.signal. Doing research on the signal that is sent by Jenkins in order to terminate a job (https://gist.github.com/datagrok/dfe9604cb907523f4a2f) resulted that Jenkins sends "TERM" signal upon stopping the process. Therefore I added the following + a control mechanism to see whether it works, as Jenkins will not show the rest of the log after stopping a job (will immediately show "ABORTED", see link):
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()
Sadly, I cannot find the "control" file in C:\temp of the PC on which the Jenkins Job is run.
My question: Is it a proper approach to use signal.signal(signal.SIGTERM, cleanUp)
(or should I use something else?) or did I make mistake in the usage of signal.signal?
I also tried to register cleanUp with atexit
but this didn't give me the results I hoped for either.
EDIT 1: One thing that I didn't mention above is the fact, that I need to hand over some complex inputs to the cleanUp function. I have already thought about using post build actions within a pipeline.
EDIT 2: As mentioned below, in theory it would be possible to hand over the inputs to recreate the object. However, this recreation is quite cumbersome and since I only want to have a quick clean up, which is not possible if I need to recreate the whole process, I try to avoid this option.
Thanks a lot!
Upvotes: -2
Views: 218
Reputation: 3303
A proper approach would be to use the built-in functionality - Jenkinsfile syntax has a block specifically dedicated for your use case:
From Pipeline Syntax:
The
post
section defines one or more additional steps that are run upon the completion of a Pipeline’s or stage’s run (depending on the location of the post section within the Pipeline).post
can support any of the following post-condition blocks:always
,changed
,fixed
,regression
,aborted
,failure
,success
,unstable
,unsuccessful
, andcleanup
. These condition blocks allow the execution of steps inside each condition depending on the completion status of the Pipeline or stage. The condition blocks are executed in the order shown below.
// 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"
}
}
}
Depending on your goal, you can choose any post condition(s) to use, and combine them, too.
I need to hand over some inputs to the cleanUp function
In your example, cleanUp()
does not take any arguments. But nevertheless, the syntax of aborted
, cleanup
, or any other post
block is the same as of steps
within any stage
:
Post-condition blocks contain steps the same as the
steps
section.
That means you have the same control over the variables - you can set them in the previous stages and use in your function. Note the change of single quotes to double quotes to enable the Groovy string interpolation.
Upvotes: 1