How to capture returnStdout in an script command when the command returns an error

I have a pipeline in a Windows server that is using git and sfdx commands to make some deployments in SF.
As I need to capture the error information received from SF if the deployment has any error, the script of the deployment command is executed with returnStdout:true.
The pipeline is working as expected when the deployment is correct, but when that command returns an error, even in the log I can see that the command is executing as expected and returning the information in json format, as the command is returning Status = 1, the pipeline is stopped and, even if I include the command in a try-catch block, the standard out is not captured in the assigned variable (it is capturing a 0 instead of the actual standard out), so I can´t continue with the process.
There is a way to continue with the execution and have the standard out stored even if the command is returning a Status = 1?

Javier Carvajal

Hi @JavierCarvajal, and welcome to the Jenkins community!

I presume that you’re using the bat step to run your commands, given that this is on a Windows server? This is a corner case which isn’t well handled by the bat step, but there’s a way around it. The return code of the whole script is just the return status of the last command in the block, so you could probably add an echo command (maybe something like echo Finished) to the end of your script block and the script should never “fail”. You’ll just have to handle the failure case yourself by checking the output of the script in order to ensure the pipeline doesn’t continue if a failure occurred, as it won’t throw an exception anymore.

Something like this:

def output = bat returnStdout: true, script: '''
deploy command that may fail
echo Finished
output = output.substring(0, output.lastIndexOf('Finished'))

The call to substring just strips the “Finished” string off of the output.

1 Like

redirect stdout of the deploy command to a file and make the bat step return the exit code.
After command execution you can use the readFile or even readJSON step to read in the command output in case the command failed.

status=bat returnStatus: true, script: 'command > output'
if (status!=0) {
  result = readJSON('output')

Thank you @mtughan for your help.
I was not able to use your suggestion, most likely because I´m a newbie in Jenkins. My command needs to receive some parameters, so I must use double quotes, but double quotes don´t allow line breaks, so it raises an exception, and I was not able to follow your approach.

Finally, I was able to get it following the @mawinter69 approach to writing the outcome to a file, so thank you. For me, writing a file shouldn´t be necessary for such an easy purpose, but it is working so it´s fine.

As I said, thank you both for your great help.

Javier Carvajal

Sounds good, glad it’s resolved! For the future, if you do need line breaks in your command and need variable interpolation, you can use triple double-quotes instead, like so:

def path = 'test.txt'
def output = bat returnStdout: true, script: """
deploy command that may fail "$path"
echo Finished
output = output.substring(0, output.lastIndexOf('Finished'))

This is the same as above, but using double-quotes instead of single-quotes to allow variable interpolation, and showing interpolating a variable in the output. If you’re curious what other string types you can use, they’re documented by Groovy (which is the language that pretty much all pipelines use) in their own documentation on Groovy’s syntax.

1 Like