passing variable to bash script in a jenkins pipeline job

51,423

Solution 1

If you are using multiline shell script with triple apostrophe, you have to use this syntax:

sh '''
 echo '''+varToPrint+'''
 other commands...
'''

(from https://medium.com/devopslinks/a-hacky-hackers-guide-to-hacking-together-jenkins-scripted-pipelines-part-3-aca73bd33eaa)

Solution 2

The example below works:

void updateApplicationVersionMaven(String version) {
    sh "mvn -B versions:set -DnewVersion=$version"
}

And a complete pipeline script (tested on Jenkins 2.7.3):

node {
    stage('test') {
        def testVar='foo'
        sh "echo $testVar"    
    }
}

EDIT (after comments): Ah, tested some more and could reproduce the issue. It's because you're sourcing the script with ". /opt/setup.sh". This influences the shell environment, and in this case breaks the Jenkins variable injection. Interesting.

EDIT2 (after comments): I believe this is an issue with the default shell that's being used (either by Jenkins or by the OS). I could reproduce the issue from the comments and was able to work around it by explicitly using bash as a shell:

def testVar='foo3'
sh "bash -c \". /var/jenkins_home/test.sh $testVar && echo \$ARCH\""

The last echo now echos the contents of testVar that was passed as an argument to the script and subsequently set by the script as an environment variable.

Solution 3

Had the same problem and the posted solutions did not work for me. Using environment variables did the trick:

env.someVar='someVal'
sh "echo  ${env.someVar}"

Solution 4

Using the returnStdout with env is another way to pass val back and forth. Example shows a unique id from uuidgen is used as a common external resource across stages.

node {
    stage('stage 1') {
        env.UNIQUE = sh(returnStdout: true, script: 'uuidgen').trim()
        sh 'echo "started `date`" > /tmp/$UNIQUE'
    }
    stage('stage 2'){
        sh 'echo "done `date`" >> /tmp/$UNIQUE'
        println sh(returnStdout: true, script: 'cat /tmp/$UNIQUE').trim()
    }
}

this will output a date to a unique file showing when it completed. uuidgen will produce a different string each time you run it.

+ echo 'done Tue Oct 22 10:12:20 CDT 2019'
[Pipeline] sh
+ cat /tmp/d7bdb6a5-badb-474d-95dd-cf831ea88a2a
[Pipeline] echo
started Tue Oct 22 10:12:20 CDT 2019
done Tue Oct 22 10:12:20 CDT 2019

Solution 5

I've solved in another way:

  1. Create a file with the desired variables
  2. Run, in the same command, both a source and the command itself

Example:

sh 'echo -n HOST_IP= > host_ip.var'
sh '/sbin/ip route|awk \'/default/ { print $3 }\' >> host_ip.var'
sh 'source host_ip.var && echo your ip: $HOST_IP'

The file ends up with

REMOTE=172.16.0.1

The output is

your ip: 172.16.0.1

Note: it is very important that the last sh command uses single quotes ('), not double ("), otherwise the pipeline tries to replace said variable

Share:
51,423
NabilG
Author by

NabilG

Updated on July 05, 2022

Comments

  • NabilG
    NabilG almost 2 years

    I have a Jenkins pipeline job in which I configure my environment with a bash script named setup.sh which looks like:

    #!/bin/bash
    export ARCH=$1
    echo "architecture = " ${ARCH}
    

    In the Jenkins pipeline script, Icall the setup.sh script with:

    def lib_arch='linux-ubuntu-14.04-x86_64-gcc4.8.4'
    sh ". /opt/setup.sh ${lib_arch}"
    

    unfortunately it seems that NO variable is passed to the setup.sh script, and the echo ${ARCH} return an empty string! I tried to instead do: sh "source /opt/setup.sh ${lib_arch}" and this fails as well with the "source not found" message. I also tried changing the first line of my script to

    #!/bin/sh
    

    but it does not help. So how can I pass a parameter to my bash script in a Jenkins pipeline script? thanks for your help.

    Update: a workaround was sugggested by Bert Jan Schrijve in this thread (see below):

    sh "bash -c \" source /opt/setup.sh ${lib_arch}\""