Jenkins pipeline script - How to use variable as a variable name

Hi

I have a groovy script as my Jenkins pipeline script, which looks something like

node(“nodeName”) {

. . . (some groovy code)

sh “”"

< This section of the shell script calculates the value of the variable varName, example being BUILD_NUMBER >

echo “${env.BUILD_ID}” # This prints expected output. Example : 51

export varName=“env.BUILD_NUMBER”

echo “${”$varName"}" # This prints the output as env.BUILD_NUMBER and not 51

“”"

}

In the above example, I had hard coded value of varName as env.BUILD_NUMBER. In my actual script, value of varName will be calculated during execution.

In bash script, this result can be achieved as follows:

#!/bin/bash
variable_1=“abc”

variable_2=variable_1

echo “${!variable_2}”

Exclamation mark (!) doesn’t work in shell script inside Jenkins pipeline

Can someone please explain, how to address my requirement ?

Thank you

Jason

In a shell script, you would want to use export

export varName="BUILD_NUMBER"

The env. portion is just useful inside of the groovy part of the pipeline. Everything in env is exported as an actual environment variable in the shell script.

@slide_o_mix

Agree that everything in env is exported to actual environment variables in the shell script

However env. does print expected output

As I had mentioned in my original post echo “${env.BUILD_ID}” # This prints expected output. Example : 51

After

export varName=BUILD_NUMBER

echo “${”$varName"}"

prints the output as BUILD_NUMBER and not acuatl build number

Thank you
Jason

is that a shell echo or a pipeline echo?

for pipeline, based on jenkins - Jenkinsfile Declarative Pipeline defining dynamic env vars - Stack Overflow it looks like you can do env."$varName" but to me this seems like a code smell, and dangerously close to eval.

If your shell script is wrapped in double quotes, then ${env.BUILD_ID} is being replaced by groovy and not the shell. Can you share your pipeline (redacted)? It would help understand your context better.

@halkeye halkeye and @slide_o_mix

Thank you for replies and sorry for the delay in answering your questions
I solved my requirement through some other means and this thread can be closed

1 Like

Thank a lot for your feedback @JasonDavis :+1: .

As @halkeye says, there is indeed a code smell. I would in fact suggest that using the sh step with Groovy strings interpolation (i.e. strings with double quotes) is generally a code smell. See the Injection via Interpolation section in the manual, which can be particularly dangerous for shell scripts.

The original question can be more or less solved directly solved by using an immutable string (single quotes). The workaround against Injection via Interpolation is to pass variable via the environment, but this is already the case here.

You can achieve all this variable substitution in a safer way directly in Bash:

script {
    env.BUILD_ID = "1234"
    env.BUILD_NUMBER = "5678"
}

sh '''#!/bin/bash
# The double-quotes here belong to the shell script,
# nothing to do with the Groovy string.
echo "$BUILD_ID"
varName="BUILD_NUMBER"

# Bash will expand this as echo "$BUILD_NUMBER", which will use the environment
# variable defined earlier, inside this shell script or passed to env in the groovy
# script
echo "${!varName}"
'''

Note: this way of expanding variables is specific to Bash and might require a different syntax with other shells (hence the #!/bin/bash at the start). If needed, you can check the shell running sh steps by default using sh 'readlink /proc/$$/exe'.

1 Like