Reputation: 170846
From time to time I encounter jobs that end-up putting Jenkins down because they log too much to the console, sometimes due to an more or less endless loop or too much verbosity.
I am looking for a solution that would prevent/stop/kill spamming jobs.
We are using Jenkins pipelines and all these occasional spamming jobs are inside sh()
, which makes me think that maybe we should add some kind of smart wrapper.
Please, do not suggest fixing the spamming source instead. I asked this question because I want to prevent this kind of issue from outside the potential spammer script, that's because we have hundreds of jobs and because is impossible to avoid a sooner or later spamming bug caused by a developer mistake.
Shortly: we cannot control what is run inside the shell script, but we can control how the shell is run.
Upvotes: 3
Views: 5468
Reputation: 31
There is a plugin that stops jobs if their console log has exceeded a defined size limit.
It is called "Build log file size checker"
If your normally successful job logs are consistent in size, and do not vary hugely, then this could help you distinguish the looping or spamming ones.
Upvotes: 3
Reputation: 170846
After many hours wasted with various attempts to address this I was able to come up with a working solution that looks like:
def sh2(script) {
sh '''( ''' + script + ''' ) 2>&1 | tee output.log | awk -v offset=${MAX_LINES:-200} '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) { if (!match(a[i],"^[[:space:]]*$")) print a[i]} }
}
You can find the latest version at https://github.com/ssbarnea/rhos-ci/blob/master/vars/sh2.groovy in case I will find other bugs or improvements.
As you can see it will limit both head and tail to 200 lines if MAX_LINES is not defined. If defined it will be used.
This solution is the only one that does not repeat output when the total number of lines is <200. Also it does work in streaming mode, so you do see the output in real time.
Note: the linked version has extra features, like ability to log full output to auto-sequenced log files.
Upvotes: 1
Reputation: 1509
You can add the returnStdout variable to your sh
calls like so:
node(){
// Eliminates returned output (you can also redirect this to a variable!)
sh returnStdout: true, script: 'echo hi; echo hi; echo hi; echo hi;'
// Has the normal output
sh script: 'echo hi; echo hi; echo hi; echo hi;'
}
Which changes to the output like so:
[Pipeline] node
Running on ***
[Pipeline] {
[Pipeline] sh
[***] Running shell script
+ echo hi
+ echo hi
+ echo hi
+ echo hi
[Pipeline] sh
[***] Running shell script
+ echo hi
hi
+ echo hi
hi
+ echo hi
hi
+ echo hi
hi
[Pipeline] }
[Pipeline] // node
If you need to automate this so that everybody does this by default, you should look into building a Groovy Shared Library that is auto loaded in your Jenkins instance (I recommend this for more large users anyways!). Once you have that set up, make a new script for executing shell steps and ask users to use that instead of the normal sh
step
Here's a good starting doc for that stuff: https://jenkins.io/doc/book/pipeline/shared-libraries/
Upvotes: 0