Jenkins sits at the heart of the DevOps toolchain, and CI/CD pipelines require writing Pipeline scripts. Getting started with Jenkins is straightforward—after a quick look at the documentation, concepts like agent, stages, and steps become clear, and you can quickly scaffold a pipeline.
However, when filling in the details, particularly how to work with environment variables (built-in and custom), many developers feel confused and waste significant time. This guide helps you quickly master environment variables.
Prerequisites
To follow along with hands-on practice, you'll need a running Jenkins instance. If you don't have one available, you can spin one up quickly using Docker:
docker container run --rm -p 8080:8080 -p 50000:50000 --name=jenkins -v $(pwd):/var/jenkins_home jenkins/jenkins
Once running, open your browser to localhost:8080 and:
- Enter the temporary admin password from the terminal to log in
- Install the recommended plugins
- Create a new Item of type "Pipeline"
- Click "Configure" on the left sidebar
- In the Pipeline section at the bottom, enter the scripts we'll write for testing
Understanding Jenkins Environment Variables
Jenkins environment variables are global variables exposed through the
envkeyword, accessible anywhere in the Jenkinsfile.
This concept is essentiallly the same as global variables in programming languages.
Viewing Built-in Environment Variables
Jenkins provides numerous built-in environment variables. There are two ways to view them:
Method 1
Access ${YOUR_JENKINS_HOST}/env-vars.html directly in your browser, for example http://localhost:8080/env-vars.html. Each variable's purpose is clearly documented.
Method 2
Execute the printenv shell command:
pipeline {
agent any
stages {
stage("Display Environment Variables") {
steps {
sh "printenv"
}
}
}
}
Click Save, then Build. The console output will display all environment variables and their current vallues.
Using both methods together is typically most effective.
Reading Environment Variables
The env keyword exposes environment variables, but when reading Jenkins' built-in variables, env is optional. However, you must always wrap variable names with ${...}. Using BUILD_NUMBER as an example:
pipeline {
agent any
stages {
stage("Reading Environment Variables") {
steps {
echo "With env keyword: ${env.BUILD_NUMBER}"
echo "Without env keyword: ${BUILD_NUMBER}"
sh 'echo "In shell: $BUILD_NUMBER"'
}
}
}
}
The results are identical. Regardless of the variations, remember the first method—it's the safest approach.
While built-in environment variables are useful, they don't always satisfy custom pipeline logic requirements. You need to know how to define and use custom environment variables.
Custom Jenkins Environment Variables
Jenkins pipelines support declarative and imperative (scripted) syntax, with slightly different ways to define environment variables. There are three methods in total.
Consider this practical example:
pipeline {
agent any
environment {
GLOBAL_VAR = "initial_value"
}
stages {
stage("Custom Environment Variables") {
environment {
STAGE_VAR = "custom_name"
}
steps {
echo "GLOBAL_VAR = ${env.GLOBAL_VAR}"
echo "STAGE_VAR = ${env.STAGE_VAR}"
script {
env.SCRIPT_VAR = "dynamically_created"
}
echo "SCRIPT_VAR = ${env.SCRIPT_VAR}"
withEnv(["BLOCK_VAR=initialized"]) {
echo "BLOCK_VAR = ${env.BLOCK_VAR}"
}
}
}
}
}
Important: In withEnv(["BLOCK_VAR=initialized"]), the = sign must have no spaces on either side—it must be key=value format.
Pipelines typically contain multiple stages, and environment variables often have different values across stages. After learning how to set and read environment variables, you need to know how to override them.
Overriding Jenkins Environment Variables
Overriding environment variables is where Jenkins becomes most confusing. Remember these three rules to handle everything:
- The
withEnv(["VAR=value"]) {}block can override any environment variable - Variables defined in
environment {}blocks cannot be overridden by script-based variable assignments (env.key="value") - Script-based variables can only override other script-based variables
These are strict rules. Anything not covered by these three rules is permitted.
Three rules can be overwhelming, so let's illustrate with an example:
pipeline {
agent any
environment {
BOOK_TITLE = "Educated"
AUTHOR = "Westover"
}
stages {
stage("Initial Values") {
environment {
// Overrides the variable from line 6
AUTHOR = "Tara"
// Overrides a built-in environment variable
BUILD_NUMBER = "10"
}
steps {
// Prints "BOOK_TITLE = Educated"
echo "BOOK_TITLE = ${env.BOOK_TITLE}"
// Prints "AUTHOR = Tara"
echo "AUTHOR = ${env.AUTHOR}"
// Prints "BUILD_NUMBER = 10"
echo "BUILD_NUMBER = ${env.BUILD_NUMBER}"
script {
// Creates a script-based environment variable
env.DYNAMIC_COUNTER = "1"
}
}
}
stage("Override Variables") {
steps {
script {
// This will NOT override BOOK_TITLE, violating Rule No.2
env.BOOK_TITLE = "Hillbilly"
// This WILL override DYNAMIC_COUNTER, following Rule No.3
env.DYNAMIC_COUNTER = "2"
}
// BOOK_TITLE still prints "Educated" (override failed)
echo "BOOK_TITLE = ${env.BOOK_TITLE}"
// Prints "DYNAMIC_COUNTER = 2"
echo "DYNAMIC_COUNTER = ${env.DYNAMIC_COUNTER}"
// BOOK_TITLE WILL be overridden, following Rule No.1
withEnv(["BOOK_TITLE=Educated"]) {
// Prints "BOOK_TITLE = Educated"
echo "BOOK_TITLE = ${env.BOOK_TITLE}"
}
// Same principle applies
withEnv(["BUILD_NUMBER=15"]) {
// Prints "BUILD_NUMBER = 15"
echo "BUILD_NUMBER = ${env.BUILD_NUMBER}"
}
}
}
}
}
Run the pipeline to verify the results.
With basic settings covered, you may have noticed that Jenkins environment variables differ from programming language variables. The latter can assign objects to variables, but Jenkins cannot—all values in Jenkinsfiles are treated as Strings. Is there no way to use Boolean values?
Using Boolean Values in Jenkins
If you set a variable to false, Jenkins converts it to the string "false". To use Booleans for conditional logic, you must call the toBoolean() method:
pipeline {
agent any
environment {
TOGGLE_FLAG = false
}
stages {
stage("Boolean Handling") {
steps {
script {
// "Hello" prints because non-empty strings are treated as Boolean.True
if (env.TOGGLE_FLAG) {
echo "Hello"
}
// Proper Boolean comparison
if (env.TOGGLE_FLAG.toBoolean() == false) {
echo "Condition matched"
}
// Another proper Boolean check
if (!env.TOGGLE_FLAG.toBoolean()) {
echo "Flag is false"
}
}
}
}
}
}
Run the pipeline to see the output.
When writing Pipelines, shell scripting is often necessary. Sometimes you need to capture shell command output and assign it to an environment variable. Jenkins supports this use case.
Assigning Shell Output to Environment Variables
The technique is simple: use sh(script: 'command', returnStdout: true)
pipeline {
agent any
environment {
DIRECTORY_LISTING = "${sh(script: 'ls -lah', returnStdout: true).trim()}"
}
stages {
stage("Capture Shell Output") {
steps {
echo "DIRECTORY_LISTING = ${env.DIRECTORY_LISTING}"
}
}
}
}
The trim() method removes trailing whitespace from the command output.