Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jenkins: Pipeline sh bad substitution error

A step in my pipeline uploads a .tar to an artifactory server. I am getting a Bad substitution error when passing in env.BUILD_NUMBER, but the same commands works when the number is hard coded. The script is written in groovy through jenkins and is running in the jenkins workspace.

sh 'curl -v --user user:password --data-binary ${buildDir}package${env.BUILD_NUMBER}.tar -X PUT "http://artifactory.mydomain.com/artifactory/release-packages/package${env.BUILD_NUMBER}.tar"' 

returns the errors:

[Pipeline] sh [Package_Deploy_Pipeline] Running shell script /var/lib/jenkins/workspace/Package_Deploy_Pipeline@tmp/durable-4c8b7958/script.sh: 2:  /var/lib/jenkins/workspace/Package_Deploy_Pipeline@tmp/durable-4c8b7958/script.sh: Bad substitution [Pipeline] } //node [Pipeline] Allocate node : End [Pipeline] End of Pipeline ERROR: script returned exit code 2 

If hard code in a build number and swap out ${env.BUILD_NUMBER} I get no errors and the code runs successfully.

sh 'curl -v --user user:password --data-binary ${buildDir}package113.tar -X PUT "http://artifactory.mydomain.com/artifactory/release-packages/package113.tar"' 

I use ${env.BUILD_NUMBER} within other sh commands within the same script and have no issues in any other places.

like image 951
Stephen Nichols Avatar asked May 13 '16 21:05

Stephen Nichols


People also ask

What is SH in Jenkins pipeline?

On Linux, BSD, and Mac OS (Unix-like) systems, the sh step is used to execute a shell command in a Pipeline. Jenkinsfile (Declarative Pipeline) pipeline { agent any stages { stage('Build') { steps { sh 'echo "Hello World"' sh ''' echo "Multiline shell steps works too" ls -lah ''' } } } }

What is bad substitution in shell script?

Bad Substitution Error Related to Command Substitution One circumstance in which this error occurs is when you want to use command substitution but by mistake you use curly braces instead of parentheses. Command substitution allows to store the output of a Bash command (as complex as you want) into a variable.


2 Answers

This turned out to be a syntax issue. Wrapping the command in ''s caused ${env.BUILD_NUMBER to be passed instead of its value. I wrapped the whole command in "s and escaped the nested. Works fine now.

sh "curl -v --user user:password --data-binary ${buildDir}package${env.BUILD_NUMBER}.tar -X PUT \"http://artifactory.mydomain.com/artifactory/release-packages/package${env.BUILD_NUMBER}.tar\"" 
like image 174
Stephen Nichols Avatar answered Sep 18 '22 20:09

Stephen Nichols


In order to Pass groovy parameters into bash scripts in Jenkins pipelines (causing sometimes bad substitions) You got 2 options:

The triple double quotes way [ " " " ] OR the triple single quotes way [ ' ' ' ]

  1. In triple double quotes you can render the normal parameter from groovy using ${someVariable} ,if it's environment variable ${env.someVariable} , if it's parameters injected into your job ${params.someVariable}

example:

     def YOUR_APPLICATION_PATH= "${WORKSPACE}/myApp/"        sh """#!/bin/bash       cd ${YOUR_APPLICATION_PATH}       npm install       """ 
  1. In triple single quotes things getting little bit tricky, you can pass the parameter to environment parameter and using it by "\${someVaraiable}" or concating the groovy parameter using ''' + someVaraiable + '''

examples:

   def YOUR_APPLICATION_PATH= "${WORKSPACE}/myApp/"     sh '''#!/bin/bash           cd ''' + YOUR_APPLICATION_PATH + '''           npm install     ''' 

OR

   pipeline{      agent { node { label "test" } }      environment {        YOUR_APPLICATION_PATH = "${WORKSPACE}/myapp/"      }       continue...      continue...      continue...       sh '''#!/bin/bash           cd "\${YOUR_APPLICATION_PATH}"           npm install     '''      //OR     sh '''#!/bin/bash           cd "\${env.YOUR_APPLICATION_PATH}"           npm install     ''' 
like image 26
avivamg Avatar answered Sep 21 '22 20:09

avivamg