当我尝试创建一个Jenkins项目时,我观察到一个奇怪的行为,这个项目有Ant步骤接受任何字符串参数供Ant使用。看起来Ant以某种方式接收了一些不正确的内容作为参数。
首先,我登录到安装Jenkins的同一个系统,并编写了一个简单的ant构建文件:
<?xml version="1.0"?>
<!--DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "/usr/src/ant/project.dtd"-->
<project name="many-params" default="run">
<target name="run">
<echo message="first Param: ${firstparam}"/>
<echo message="second Param: ${secondparam}"/>
</target>
</project>
然后运行设置了参数的ant,得到了预期的输出:
$ ant -Dfirstparam=A -Dsecondparam=B
Buildfile: /tmp/build-dir/build.xml
run:
[echo] first Param: A
[echo] second Param: B
BUILD SUCCESSFUL
Total time: 0 seconds
接下来,我在Jenkins中设置了一个同样的项目。我的Jenkins系统规格如下:
- OS:
- Linux amd64 2.6.32-504.1.3.el6.x86_64 詹金斯
- : 版本。1.618
- JRE Jenkins正在运行: Oracle 1.7.0_55-b13
- 蚂蚁插件版本: 1.2
- 项目用JRE: Oracle 1.6.45 32位
- 项目使用的Ant: 1.8.2
我已经设置了8个连续步骤的工作,4个预备shell脚本片段重写build.xml与稍微不同的参数名称(没有分隔符,虚线分隔符,点分隔符)和4个Ant构建步骤调用Ant,试图传递相应的参数。
作业目录中准备好的config.xml如下:
<?xml version='1.0' encoding='UTF-8'?>
<project>
<actions/>
<description>A simple task to test many parameter setting for jenkins calling ant tasks</description>
<logRotator class="hudson.tasks.LogRotator">
<daysToKeep>-1</daysToKeep>
<numToKeep>10</numToKeep>
<artifactDaysToKeep>-1</artifactDaysToKeep>
<artifactNumToKeep>-1</artifactNumToKeep>
</logRotator>
<keepDependencies>false</keepDependencies>
<scm class="hudson.scm.NullSCM"/>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<jdk>Oracle Java 1.6.45 32-bit JRE</jdk>
<triggers/>
<concurrentBuild>false</concurrentBuild>
<builders>
<hudson.tasks.Shell>
<command>echo "STEP 1: Pass parameters with no separators in names"
cat > build.xml << EOF
<?xml version="1.0"?>
<!--DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "/usr/src/ant/project.dtd"-->
<project name="many-params" default="run">
<target name="run">
<echo message="first Param: ${paramfirst}"/>
<echo message="second Param: ${paramsecond}"/>
</target>
</project>
EOF</command>
</hudson.tasks.Shell>
<hudson.tasks.Ant plugin="ant@1.2">
<targets>run</targets>
<antName>Ant 1.8.2</antName>
<properties>paramfirst=A
paramsecond=B</properties>
</hudson.tasks.Ant>
<hudson.tasks.Shell>
<command>rm build.xml
echo
echo "STEP 2: Pass parameters with separated by dashes in names"
cat > build.xml << EOF
<?xml version="1.0"?>
<!--DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "/usr/src/ant/project.dtd"-->
<project name="many-params" default="run">
<target name="run">
<echo message="first Param: ${param-first}"/>
<echo message="second Param: ${param-second}"/>
</target>
</project>
EOF</command>
</hudson.tasks.Shell>
<hudson.tasks.Ant plugin="ant@1.2">
<targets>run</targets>
<antName>Ant 1.8.2</antName>
<properties>param-first=A
param-second=B</properties>
</hudson.tasks.Ant>
<hudson.tasks.Shell>
<command>echo
echo "STEP 3: Same, but with parameters on the same line in Ant Plugin step setup"</command>
</hudson.tasks.Shell>
<hudson.tasks.Ant plugin="ant@1.2">
<targets>run</targets>
<antName>Ant 1.8.2</antName>
<properties>param-first=A param-second=B</properties>
</hudson.tasks.Ant>
<hudson.tasks.Shell>
<command>rm build.xml
echo
echo "STEP 4: Pass parameters with separated by dots in names"
cat > build.xml << EOF
<?xml version="1.0"?>
<!--DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "/usr/src/ant/project.dtd"-->
<project name="many-params" default="run">
<target name="run">
<echo message="first Param: ${param.first}"/>
<echo message="second Param: ${param.second}"/>
</target>
</project>
EOF</command>
</hudson.tasks.Shell>
<hudson.tasks.Ant plugin="ant@1.2">
<targets>run</targets>
<antName>Ant 1.8.2</antName>
<properties>param.first=A
param.second=B</properties>
</hudson.tasks.Ant>
</builders>
<publishers/>
<buildWrappers>
<hudson.plugins.ws__cleanup.PreBuildCleanup plugin="ws-cleanup@0.26">
<deleteDirs>false</deleteDirs>
<cleanupParameter></cleanupParameter>
<externalDelete></externalDelete>
</hudson.plugins.ws__cleanup.PreBuildCleanup>
</buildWrappers>
</project>
构建任务给了我以下输出:
Started by user Alexander Krasnyansky
[EnvInject] - Loading node environment variables.
Building remotely on j03_uk1ps41 (buildslaves) in workspace /var/lib/jenkins03/workspace/akrasnyansky/ManyParams/ant-param-test
Deleting project workspace... done
[ant-param-test] $ /bin/sh -xe /tmp/hudson2203137136163442442.sh
+ echo 'STEP 1: Pass parameters with no separators in names'
STEP 1: Pass parameters with no separators in names
+ cat
[ant-param-test] $ /usr/local/apache-ant-1.8.2/bin/ant -Dparamfirst=A -Dparamsecond=B run
Buildfile: /var/lib/jenkins03/workspace/akrasnyansky/ManyParams/ant-param-test/build.xml
run:
[echo] first Param:
[echo] second Param:
BUILD SUCCESSFUL
Total time: 0 seconds
[ant-param-test] $ /bin/sh -xe /tmp/hudson5869719507232196626.sh
+ rm build.xml
+ echo
+ echo 'STEP 2: Pass parameters with separated by dashes in names'
STEP 2: Pass parameters with separated by dashes in names
+ cat
[ant-param-test] $ /usr/local/apache-ant-1.8.2/bin/ant -Dparam-first=A -Dparam-second=B run
Buildfile: /var/lib/jenkins03/workspace/akrasnyansky/ManyParams/ant-param-test/build.xml
run:
[echo] first Param: first
[echo] second Param: second
BUILD SUCCESSFUL
Total time: 0 seconds
[ant-param-test] $ /bin/sh -xe /tmp/hudson1052316660761572548.sh
+ echo
+ echo 'STEP 3: Same, but with parameters on the same line in Ant Plugin step setup'
STEP 3: Same, but with parameters on the same line in Ant Plugin step setup
[ant-param-test] $ /usr/local/apache-ant-1.8.2/bin/ant "-Dparam-first=A param-second=B" run
Buildfile: /var/lib/jenkins03/workspace/akrasnyansky/ManyParams/ant-param-test/build.xml
run:
[echo] first Param: first
[echo] second Param: second
BUILD SUCCESSFUL
Total time: 0 seconds
[ant-param-test] $ /bin/sh -xe /tmp/hudson4427994032931026249.sh
+ rm build.xml
+ echo
+ echo 'STEP 4: Pass parameters with separated by dots in names'
STEP 4: Pass parameters with separated by dots in names
+ cat
/tmp/hudson4427994032931026249.sh: line 5: <?xml version="1.0"?>
<!--DOCTYPE project PUBLIC "-//ANT//DTD project//EN" "/usr/src/ant/project.dtd"-->
<project name="many-params" default="run">
<target name="run">
<echo message="first Param: ${param.first}"/>
<echo message="second Param: ${param.second}"/>
</target>
</project>
: bad substitution
Build step 'Execute shell' marked build as failure
Started calculate disk usage of build
Finished Calculation of disk usage of build in 0 seconds
Started calculate disk usage of workspace
Finished Calculation of disk usage of workspace in 0 seconds
Finished: FAILURE
这就产生了很多问题:
- 为什么在步骤1中没有打印任何值?
- 如何使用字符串值"first"one_answers"second"而不是"A"one_answers"B",我在第2步提供?
- 为什么在第3步畸形行"-Dparam-first=A param-second=B"(通过将两个参数放在詹金斯步骤设置中的同一行:param-first=A param-second=B)的工作就像在第2步"-Dparam-first=A -Dparam-second=B"一样好?我应该在这里失败,就像我在shell中运行相同的一样。
- 第4步的点有什么问题?为什么这里会产生严重的替换错误?
非常感谢您对这些问题的建议。
你的问题是重写build.xml
。我真的不明白你为什么要那样做。但是让我们开始吧。
tl;dr: 你混淆了Shell和Ant变量的行为:如何转义它们以及当它们未定义时会发生什么
你有一个"执行Shell"构建步骤,在那里你使用cat
将新内容放入文件。
到此为止。要么删除其他构建步骤,要么简单地在cat
命令后放置一个巨大的sleep
。现在在您的工作区中查看生成的build.xml
。你会看到:<echo message="first Param: "/>
如您所见,在该回显行中实际上没有参数。因此,当它运行时,它不输出除文本以外的任何内容,这并不奇怪。为什么会这样呢?
1。您的cat
命令在Shell中运行。您没有在first Param: ${paramfirst}
中转义参数的美元符号$
。因此,在运行时,Shell将${paramfirst}
视为一个变量,并尝试查找它的值。没有,所以Shell用什么都不替换它(如果这是Ant, Ant会逐字打印未定义的变量)
您需要从Shell转义该变量,因此写入first Param: ${paramfirst}
。这将生成正确的build.xml
,所有工作都将从那里开始。
2。 linux环境变量名中允许的字符或shell变量是否可以包含-字符?
连字符-
是不允许的Shell变量名。
发生的是Shell看到变量定义${
之后,它向前查找连字符-
(因为连字符不能是变量名),并在那里分割字符串。所以在${param-first}
中,Shell认为${param
是变量,-first}
是畸形文本。第一个用空替换,其余部分打印出来(由于Shell的特性,}
被使用)
3。"调用Ant"构建步骤需要key=value
样式的参数,每行一个。然后,它将取每一行,以-D
作为前缀,并将多行串在一起形成最终的命令行。
所以这个:
param-first=A
param-second=B
变成这样:
-Dparam-first=A
-Dparam-second=B
然后串成:-Dparam-first=A -Dparam-second=B
当你这样做的时候:
param-first=A param-second=B
它变成了这样(记住:每行一个):
-Dparam-first=A param-second=B
注意只有一个-D
,因为每行只有一个参数
4。 Shell不允许在变量名中出现句号.
。时期。(双关语)。参见1的答案。和2.。但是,您可以在Ant变量名称中使用句号和连字符,但出于一致性原因,我建议不要这样做。