jenkins pipeline - How do I get the output of a shell command executed using into a variable from Jenkinsfile (groovy)?

ID : 10440

viewed : 87

Tags : groovyjenkins-pipelinegroovy

Top 5 Answer for jenkins pipeline - How do I get the output of a shell command executed using into a variable from Jenkinsfile (groovy)?

vote vote

92

The latest version of the pipeline sh step allows you to do the following;

// Git committer email GIT_COMMIT_EMAIL = sh (     script: 'git --no-pager show -s --format=\'%ae\'',     returnStdout: true ).trim() echo "Git committer email: ${GIT_COMMIT_EMAIL}" 

Another feature is the returnStatus option.

// Test commit message for flags BUILD_FULL = sh (     script: "git log -1 --pretty=%B | grep '\\[jenkins-full]'",     returnStatus: true ) == 0 echo "Build full flag: ${BUILD_FULL}" 

These options where added based on this issue.

See official documentation for the sh command.

For declarative pipelines (see comments), you need to wrap code into script step:

script {    GIT_COMMIT_EMAIL = sh (         script: 'git --no-pager show -s --format=\'%ae\'',         returnStdout: true     ).trim()     echo "Git committer email: ${GIT_COMMIT_EMAIL}" } 
vote vote

84

Current Pipeline version natively supports returnStdout and returnStatus, which make it possible to get output or status from sh/bat steps.

An example:

def ret = sh(script: 'uname', returnStdout: true) println ret 

An official documentation.

vote vote

72

quick answer is this:

sh "ls -l > commandResult" result = readFile('commandResult').trim() 

I think there exist a feature request to be able to get the result of sh step, but as far as I know, currently there is no other option.

EDIT: JENKINS-26133

EDIT2: Not quite sure since what version, but sh/bat steps now can return the std output, simply:

def output = sh returnStdout: true, script: 'ls -l' 
vote vote

67

If you want to get the stdout AND know whether the command succeeded or not, just use returnStdout and wrap it in an exception handler:

scripted pipeline

try {     // Fails with non-zero exit if dir1 does not exist     def dir1 = sh(script:'ls -la dir1', returnStdout:true).trim() } catch (Exception ex) {     println("Unable to read dir1: ${ex}") } 

output:

[Pipeline] sh [Test-Pipeline] Running shell script + ls -la dir1 ls: cannot access dir1: No such file or directory [Pipeline] echo unable to read dir1: hudson.AbortException: script returned exit code 2 

Unfortunately hudson.AbortException is missing any useful method to obtain that exit status, so if the actual value is required you'd need to parse it out of the message (ugh!)

Contrary to the Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html the build is not failed when this exception is caught. It fails when it's not caught!

Update: If you also want the STDERR output from the shell command, Jenkins unfortunately fails to properly support that common use-case. A 2017 ticket JENKINS-44930 is stuck in a state of opinionated ping-pong whilst making no progress towards a solution - please consider adding your upvote to it.

As to a solution now, there could be a couple of possible approaches:

a) Redirect STDERR to STDOUT 2>&1 - but it's then up to you to parse that out of the main output though, and you won't get the output if the command failed - because you're in the exception handler.

b) redirect STDERR to a temporary file (the name of which you prepare earlier) 2>filename (but remember to clean up the file afterwards) - ie. main code becomes:

def stderrfile = 'stderr.out' try {     def dir1 = sh(script:"ls -la dir1 2>${stderrfile}", returnStdout:true).trim() } catch (Exception ex) {     def errmsg = readFile(stderrfile)     println("Unable to read dir1: ${ex} - ${errmsg}") } 

c) Go the other way, set returnStatus=true instead, dispense with the exception handler and always capture output to a file, ie:

def outfile = 'stdout.out' def status = sh(script:"ls -la dir1 >${outfile} 2>&1", returnStatus:true) def output = readFile(outfile).trim() if (status == 0) {     // output is directory listing from stdout } else {     // output is error message from stderr } 

Caveat: the above code is Unix/Linux-specific - Windows requires completely different shell commands.

vote vote

50

this is a sample case, which will make sense I believe!

node('master'){     stage('stage1'){     def commit = sh (returnStdout: true, script: '''echo hi     echo bye | grep -o "e"     date     echo lol''').split()       echo "${commit[-1]} "      } } 

Top 3 video Explaining jenkins pipeline - How do I get the output of a shell command executed using into a variable from Jenkinsfile (groovy)?

Related QUESTION?