如何从Jenkinsfile向bash传递包含空格的字符串?
解决Jenkins传递含空格参数给Bash脚本的问题
问题分析
核心矛盾是Groovy字符串插值与Bash参数解析的规则冲突:
- 之前将opts拼接成单个字符串传递时,Bash会把整个字符串当作一个参数,而非拆分出多个独立参数
- 尝试用Groovy列表传递参数时,Groovy默认的列表
toString()行为会给元素套上单引号,导致Bash脚本接收到异常格式的参数 - 用EOF输入重定向的方式完全错误,Java应用只会读取命令行参数,不会从标准输入获取参数
正确解决方案
1. 修改Jenkinsfile:用列表管理参数,生成合法的Bash命令
将opts改为Groovy列表存储每个独立参数,再转换为Bash能正确解析的带引号参数串:
pipeline { agent any options { disableConcurrentBuilds() } stages { stage('Run') { steps { script { def subdom = 'example' // 用列表存储每个独立参数,带空格的参数直接写入即可 def opts = [ '-test', '-comment="test comment"' ] // 合并子域名和所有opts参数 def allArgs = [subdom] + opts // 为每个参数添加双引号,避免空格导致的参数拆分错误 def cmdArgs = allArgs.collect { "\"${it}\"" }.join(' ') // 执行Bash脚本 sh "bash -x /usr/share/jenkins/ref/runApp.sh ${cmdArgs}" } } } } }
2. 修改Bash脚本:正确接收并传递所有参数
保持脚本简洁,接收第一个参数作为子域名,剩余参数原样传递给Java应用(注意"$@"必须加双引号,确保带空格的参数被完整传递):
#!/bin/bash # 接收子域名参数 subdom="$1" # 移除第一个参数,剩余内容全为Java应用的参数 shift # 执行Java应用,传递所有剩余参数 java "myApp.${subdom}.com" "$@"
验证逻辑
- Jenkins最终生成的命令:
bash -x /usr/share/jenkins/ref/runApp.sh "example" "-test" "-comment=\"test comment\"" - Bash脚本接收到的参数:
$1=example,$2=-test,$3=-comment="test comment" - Java应用会正确解析到两个独立参数:
-test和-comment="test comment"
失败原因复盘
- 单引号问题:Groovy列表直接转字符串时,默认会用单引号包裹元素(如
[-test, -comment="test comment"]转为'[-test,' '-comment="test comment"]'),这是Groovy自身的toString()行为,和Jenkins无关 - 字符串拼接传递:将opts拼成单个字符串后,Bash会把整个字符串当作一个参数,导致Java应用接收到的是包含空格的单个大参数,而非拆分后的多个参数
- EOF重定向:Java应用仅读取命令行参数,不会从标准输入获取内容,因此这种方式无法传递任何有效参数
内容的提问来源于stack exchange,提问作者CloudWatcher
相关产品推荐
相关产品推荐

