Reputation: 1223
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}\""
Upvotes: 27
Views: 81644
Reputation: 1
def lib_arch='linux-ubuntu-14.04-x86_64-gcc4.8.4'
withEnv(["ARCH=${lib_arch}"]) {
sh """. /opt/setup.sh"""
# Subsequent steps can access $ARCH
sh "echo 'Architecture in pipeline: $ARCH'"
}
Note:
withEnv
for persistent environment variables.
(dot) for sourcing scripts within sh
If there is a pipeline with environment variable to be passed
pipeline {
environment {
LIB_ARCH = 'linux-ubuntu-14.04-x86_64-gcc4.8.4'
}
stages {
stage('Deploy') {
steps {
script {
def arch = env.LIB_ARCH
sh """. /opt/setup.sh ${arch}"""
}
}
}
}
}
Note:
env.
for accessing environment variablesLIB_ARCH
is correctly defined in the pipeline environmentUpvotes: 0
Reputation: 2398
In my case I just needed to save initial directory (where workspace gets mount) into docker agent. So it could be used later as an input to some other build command. Normally I'd prefer to use bash variable, but after trial and error I ended up doing this:
stage('Build') {
agent {
docker { ... }
}
steps {
script {
MYPWD = sh( script: 'pwd', returnStdout: true );
}
sh "echo $MYPWD"
}
}
Upvotes: 0
Reputation: 41
https://stackoverflow.com/a/55454037/6432452 THANK YOU @Tony. This worked out for me! I tried everything!
For people that need 2nd pipe's status code and are forced to use bash in Jenkins because of the "Bad Substitution" Error when using sh.
def verify(name, config) {
script {
sh '''
#!/bin/bash
docker-compose run --rm -e HOST='''+name+''' test rake -f test/Rakefile test_'''+config+''' | tee -a test-output-'''+config+'''.log; test "${PIPESTATUS[0]}" -eq 0
'''
}
}
You also have to put shebang on the same line as '''
Upvotes: 4
Reputation: 2086
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
Upvotes: 4
Reputation: 1163
If you are using multiline shell script with triple apostrophe, you have to use this syntax:
sh '''
echo '''+varToPrint+'''
other commands...
'''
Upvotes: 21
Reputation: 693
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}"
Upvotes: 9
Reputation: 533
I've solved in another way:
source
and the command itselfExample:
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
Upvotes: 1
Reputation: 1531
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.
Upvotes: 9