Capturing Shell Command Output in Jenkins Pipeline
Jenkins pipelines provide a powerful way to automate build, test, and deployment processes. Often, you’ll need to execute shell commands within your pipeline and capture their output for use in subsequent steps. This tutorial explains how to effectively capture the output of shell commands within a Jenkins pipeline using the sh
step.
Understanding the sh
Step
The sh
step in Jenkins pipelines is used to execute shell scripts or individual commands. Historically, capturing the output of these commands was a challenge. However, modern Jenkins pipelines provide built-in mechanisms to address this.
Capturing Output with returnStdout
The simplest and recommended way to capture the standard output of a shell command is to use the returnStdout: true
option with the sh
step. This option instructs the sh
step to return the command’s standard output as a string.
Here’s a basic example:
def commandOutput = sh(script: 'ls -l', returnStdout: true)
echo "Command Output: ${commandOutput}"
In this example:
sh(script: 'ls -l', returnStdout: true)
executes thels -l
command and captures its standard output.- The captured output is assigned to the
commandOutput
variable. echo "Command Output: ${commandOutput}"
prints the captured output to the console.
Capturing Output and Status with returnStatus
Sometimes, you need to know whether a command executed successfully or not, in addition to its output. You can use the returnStatus: true
option along with returnStdout: true
or check the return status independently.
Here’s how to check the return status:
def commandOutput = sh(script: 'ls -l', returnStdout: true)
def returnStatus = sh(script: 'ls -l', returnStatus: true)
if (returnStatus == 0) {
echo "Command executed successfully."
} else {
echo "Command failed with exit code ${returnStatus}"
}
echo "Command Output: ${commandOutput}"
The returnStatus
variable will contain the exit code of the command. A value of 0
typically indicates success, while any other value indicates an error.
Using Output in Subsequent Shell Commands
Captured output can be used as input for subsequent shell commands. This is often useful for chaining commands together or for passing data between different stages of a pipeline.
def commandOutput = sh(script: 'date +%Y-%m-%d', returnStdout: true)
sh(script: "echo 'Today is: ${commandOutput}'")
In this example, the output of the date
command is captured and then used as part of the input to the echo
command.
Handling Errors
While returnStatus
allows you to check for errors, you can also use try-catch blocks to handle exceptions. This is especially useful when the failure of a command should trigger specific actions.
try {
def commandOutput = sh(script: 'some_command_that_might_fail', returnStdout: true)
echo "Command executed successfully."
} catch (Exception e) {
echo "Command failed: ${e.getMessage()}"
// Add error handling logic here, such as failing the build or sending a notification.
}
Declarative Pipelines
If you’re using declarative pipelines, you’ll need to wrap the sh
step within a script
block to use options like returnStdout
and returnStatus
.
pipeline {
agent any
stages {
stage('Example') {
steps {
script {
def commandOutput = sh(script: 'ls -l', returnStdout: true)
echo "Command Output: ${commandOutput}"
}
}
}
}
}
Advanced Considerations
- Windows Compatibility: The examples provided are primarily for Unix-like systems. If your Jenkins agent is running Windows, you’ll need to use the appropriate Windows commands and syntax.
- Large Output: Be mindful of the amount of output you’re capturing. Capturing very large outputs can consume significant memory. Consider streaming the output to a file instead if you only need to process it incrementally.
- Security: Be cautious when using captured output in subsequent commands, especially if the output comes from untrusted sources. Sanitize the output to prevent command injection vulnerabilities.