Expansion with jenkins-cli.jar
It's true, Jenkins expands build variable names like JENKINS_URL
or BUILD_NUMBER
when they are prefixed by $
. However, there are additional transformations—rather unexpected ones—if you use jenkins-cli.jar
.
- carriage return becomes
\r
(backslash + "r")
- new line becomes
\n
(backslash plus + "n")
- tab becomes
\t
(backslash plus "t")
Here is the corresponding part of the source code of jenkins-cli.jar.
I do not know any way of escaping or quoting to keep a white space character that is part of the value of a parameter for a Jenkins job when using jenkins-cli.jar
Expansion when using "raw" ssh (without jenkins-cli.jar)
The Jenkins master handles white space, backslashes and quotes on the command line somewhat like a shell:
a
remains a
'a'
becomes a
"a b"
becomes a b
a b
is an error, because the command line parser of Jenkins will see b
a" "
becomes a
("a" plus space)
My idea was to re-implement the code that does the quoting in jenkins-cli.jar (minus the bugs when handling tab characters and the like). So here's my recipe:
For each argument, escape each backslash and
each single quote with a backslash.
Then surround it with single quotes.
Example: Instead of a'"b
, send 'a\'"b'
.
This has proven to be protect white space and quotes. And instead of using single quotes, you can use double quotes instead.
Pipeline for Testing
This is how I tested: I created the pipeline test-quoting
with the string parameter "PARAM" and the following script:
import groovy.json.JsonOutput
node {
println JsonOutput.toJson(env.PARAM)
}
Then I started the pipeline (in bash), adding an additional layer of quoting that the local shell will remove:
# for testing 'a b'
$ ssh -x -p 50022 <jenkins-server> -l <user-name> build -s -v test-quoting -p PARAM="'a b'"
# for testing the behaviour of the cli with tab character
$ java -jar jenkins-cli.jar -ssh -s <jenkins-url> -user <user-name> build -s -v test-quoting -p PARAM="$(printf '\t')"
If you are unsure about what your local shell really passes to ssh
(or any other command), prefix the command with strace -e execve
.