![Jenkins 2.x实践指南](https://wfqqreader-1252317822.image.myqcloud.com/cover/830/25449830/b_25449830.jpg)
3.7 pipeline内置基础步骤
本节介绍pipeline内置的一些步骤。作为参考内容,跳过本节不影响本书整体阅读。建议初学者跳过。
3.7.1 文件目录相关步骤
deleteDir:删除当前目录
deleteDir是一个无参步骤,删除的是当前工作目录。通常它与dir步骤一起使用,用于删除指定目录下的内容。
dir:切换到目录
默认pipeline工作在工作空间目录下,dir步骤可以让我们切换到其他目录。使用方法如下:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/39_2.jpg?sign=1738866945-OWt9T8eCw4K0SttDarIybwNZZSXHM1jC-0-7dd4de9bb5448363f93234e12485586f)
fileExists:判断文件是否存在
fileExists('/tmp/a.jar')判断/tmp/a.jar文件是否存在。如果参数是相对路径,则判断在相对当前工作目录下,该文件是否存在。结果返回布尔类型。
isUnix:判断是否为类UNIX系统
如果当前pipeline运行在一个类UNIX系统上,则返回true。
pwd:确认当前目录
pwd与Linux的pwd命令一样,返回当前所在目录。它有一个布尔类型的可选参数:tmp,如果参数值为true,则返回与当前工作空间关联的临时目录。
writeFile:将内容写入指定文件中
writeFile支持的参数有:
• file:文件路径,可以是绝对路径,也可以是相对路径。
• text:要写入的文件内容。
• encoding(可选):目标文件的编码。如果留空,则使用操作系统默认的编码。如果写的是Base64的数据,则可以使用Base64编码。
readFile:读取文件内容
读取指定文件的内容,以文本返回。readFile支持的参数有:
• file:路径,可以是绝对路径,也可以是相对路径。
• encoding(可选):读取文件时使用的编码。
示例如下:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/40_1.jpg?sign=1738866945-CdJAKgu5c6McgtKFp2VRbKPve21KV0je-0-d8e72760af62d4f644047b0ddee5c109)
3.7.2 制品相关步骤
stash:保存临时文件
stash步骤可以将一些文件保存起来,以便被同一次构建的其他步骤或阶段使用。如果整个pipeline的所有阶段在同一台机器上执行,则stash步骤是多余的。所以,通常需要stash的文件都是要跨Jenkins node使用的。关于Jenkins node的相关概念,我们会在第14章中进行介绍。
stash步骤会将文件存储在tar文件中,对于大文件的stash操作将会消耗Jenkins master的计算资源。Jenkins官方文档推荐,当文件大小为5∼100MB时,应该考虑使用其他替代方案。
stash步骤的参数列表如下:
• name:字符串类型,保存文件的集合的唯一标识。
• allowEmpty:布尔类型,允许stash内容为空。
• excludes:字符串类型,将哪些文件排除。如果排除多个文件,则使用逗号分隔。留空代表不排除任何文件。
• includes:字符串类型,stash哪些文件,留空代表当前文件夹下的所有文件。
• useDefaultExcludes:布尔类型,如果为true,则代表使用Ant风格路径默认排除文件列表。
除了name参数,其他参数都是可选的。excludes和includes使用的是Ant风格路径表达式。在3.7.5节中将简单介绍该表达式写法。
unstash:取出之前stash的文件
unstash步骤只有一个name参数,即stash时的唯一标识。通常stash与unstash步骤同时使用。以下是完整示例。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/41_1.jpg?sign=1738866945-qJMW4fHvL9K3CnMFgjOH4yqlmqZfa53Z-0-e54b03acdf39563fb36010ce08675c51)
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/42_1.jpg?sign=1738866945-Ak6atho4lxoIRwulACb4EKkCAdagayf9-0-65d43acced95569a757d0d2466b13280)
stash步骤在master节点上执行,而unstash步骤在node2节点上执行。
3.7.3 命令相关步骤
与命令相关的步骤其实是Pipeline:Nodes and Processes插件提供的步骤。由于它是Pipeline插件的一个组件,所以基本不需要单独安装。
sh:执行shell命令
sh步骤支持的参数有:
• script:将要执行的shell脚本,通常在类UNIX系统上可以是多行脚本。
• encoding:脚本执行后输出日志的编码,默认值为脚本运行所在系统的编码。
• returnStatus:布尔类型,默认脚本返回的是状态码,如果是一个非零的状态码,则会引发pipeline执行失败。如果returnStatus参数为true,则不论状态码是什么,pipeline的执行都不会受影响。
• returnStdout:布尔类型,如果为true,则任务的标准输出将作为步骤的返回值,而不是打印到构建日志中(如果有错误,则依然会打印到日志中)。除了script参数,其他参数都是可选的。
returnStatus与returnStdout参数一般不会同时使用,因为返回值只能有一个。如果同时使用,则只有returnStatus参数生效。
bat、powershell步骤
bat步骤执行的是Windows的批处理命令。powershell步骤执行的是PowerShell脚本,支持3+版本。这两个步骤支持的参数与sh步骤的一样,这里就不重复介绍了。
3.7.4 其他步骤
error:主动报错,中止当前pipeline
error 步骤的执行类似于抛出一个异常。它只有一个必需参数:message。通常省略参数:error("there's an error")。
tool:使用预定义的工具
如果在Global Tool Configuration(全局工具配置)中配置了工具,如图3-4所示,比如配置了Docker,那么可以通过tool步骤得到工具路径。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/43_1.jpg?sign=1738866945-X4UsPyxLfpJA0agdF8YApdHhZptS869b-0-d5c7832ab49bae71bad9cb51fffeaded)
图3-4 Docker installations
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/43_2.jpg?sign=1738866945-PbbYOHLK4zou0HJXHWa8mvba8pdEBFpv-0-6f95195c28804b0d51253eb4f1992955)
tool步骤支持的参数有:
• name:工具名称。
• type(可选):工具类型,指该工具安装类的全路径类名。
每个插件的type值都不一样,而且绝大多数插件的文档根本不写type值。除了到该插件的源码中查找,还有一种方法可以让我们快速找到type值,就是前往Jenkins pipeline代码片段生成器中生成该tool步骤的代码即可,如图3-5所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/44_1.jpg?sign=1738866945-FcXZJLIShtzdWM16DnZKCQyhkU01os3q-0-b0cfda7f80a6be2f6e711922c15f0086)
图3-5 生成tool步骤代码
timeout:代码块超时时间
为timeout步骤闭包内运行的代码设置超时时间限制。如果超时,将抛出一个org.jenkinsci.plugins.workflow.steps.FlowInterruptedException异常。timeout步骤支持如下参数:
• time:整型,超时时间。
• unit(可选):时间单位,支持的值有NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS、MINUTES(默认)、HOURS、DAYS。
• activity(可选):布尔类型,如果值为true,则只有当日志没有活动后,才真正算作超时。
waitUntil:等待条件满足
不断重复waitUntil块内的代码,直到条件为true。waitUntil不负责处理块内代码的异常,遇到异常时直接向外抛出。waitUntil步骤最好与timeout步骤共同使用,避免死循环。示例如下:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/44_2.jpg?sign=1738866945-vQw9LvunqCicSjx7dliFgLETYMKOCFlW-0-b4670e9b9918cd29bd3e0172ed80212d)
retry:重复执行块
执行N 次闭包内的脚本。如果其中某次执行抛出异常,则只中止本次执行,并不会中止整个retry的执行。同时,在执行retry的过程中,用户是无法中止pipeline的。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/45_1.jpg?sign=1738866945-iIMDkVDNXfWVzfDDMCrjlxZLrT5CXHfo-0-b93090fcc62e3e98f84e339ad3396a93)
sleep:让pipeline休眠一段时间
sleep步骤可用于简单地暂停pipeline,其支持的参数有:
• time:整型,休眠时间。
• unit(可选):时间单位,支持的值有NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS(默认)、MINUTES、HOURS、DAYS。
示例如下:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/45_2.jpg?sign=1738866945-26cBM7RTjvaWCs8R2eHpb9P1njLotQbs-0-2eb9a0ed5cdc3cdca063fc6430629e68)
3.7.5 小贴士
使用pipeline代码片段生成器学习
对于初学Jenkins pipeline的新人来说,如何开始写pipeline是一个坎儿。好在Jenkins提供了一个pipeline代码片段生成器,通过界面操作就可以生成代码。
进入 pipeline 项目后,单击左边的“Pipeline Syntax”菜单项(只有 pipeline 项目有),如图3-6所示。
进入“Pipeline Syntax”页面后,在右边的“Sample Step”下拉框中选择需要生成代码的步骤,并根据提示填入参数,然后单击“Generate Pipeline Script”按钮,就可以生成代码了,如图3-7所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/46_1.jpg?sign=1738866945-JcqD1Pg5VHTfUV3k5sacfbOc018pf5hG-0-254a988be17cd71bdfbe82439eb247eb)
图3-6 Pipeline Syntax菜单
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/46_2.jpg?sign=1738866945-ltKxEANrTDwd1RzxdOp0iHjs3BEDjrk9-0-31193e19674a8f34ab979ba22cb78d40)
图3-7 生成pipeline代码
使用VS Code扩展校验Jenkinsfile
不像Java语言有各种开发工具支持,Jenkinsfile从诞生以来就没有很好的工具支持,无奈只能使用VS Code文本编辑器+Groovy语法高亮进行开发。对语法的校验全凭自己对Jenkinsfile的熟悉程度。
2018年11月初,Jenkins官方博客介绍了一个VS Code扩展:Jenkins Pipeline Linter Connector,实现了对Jenkinsfile的语法校验。
在VS Code应用市场搜索“Jenkins Pipeline Linter Connector”并安装,然后对该扩展进行设置,如图3-8所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/47_1.jpg?sign=1738866945-PKISuAZGazb3ylqGmYp40E3hLPVUthMJ-0-b934d7ff060212593c5c94d8453034c8)
图3-8 设置VS Code的Jenkins pipeline扩展
然后,进入Jenkins的Manage Jenkins→Manage Configure Global Security页,确认Jenkins启用了“CSRF Protection”,如图3-9所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/47_2.jpg?sign=1738866945-kwjcyqJbvCQ5JISujrNIUjg4GxNOlCQa-0-4c9428b24e9a0fff0bfd03f2f3bd484c)
图3-9 设置Jenkins启用“CSRF Protection”
接下来,打开一个Jenkinsfile文件,调用扩展命令,如图3-10所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/48_1.jpg?sign=1738866945-b3UgY4MwNjzfaH9RXTH2YMTz9at5hLX9-0-eb062a6bf84cd70b6a2cfe2d2ce78fa2)
图3-10 执行校验Jenkinsfile命令
最后,在OUTPUT中可以看到校验结果,如图3-11所示。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/48_2.jpg?sign=1738866945-KMzzFVRAWwQgdyXtImj0iHE6BhVSHOCf-0-95dad71acd21a9900fa3826955cb0686)
图3-11 VS Code显示校验结果
值得注意的是,该扩展只能利用Jenkins API进行语法校验。比如将input步骤写成nput,校验同样通过。
使用Workspace Cleanup插件清理空间
通常,当pipeline执行完成后,并不会自动清理空间。如果需要(通常需要)清理工作空间,则可以通过Workspace Cleanup插件实现。
(1)安装Workspace Cleanup插件(地址为https://plugins.jenkins.io/ws-cleanup)。
(2)在pipeline的post部分加入插件步骤。
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/48_3.jpg?sign=1738866945-D3WJAi115f9AbVHbMQYDva2U471LYxRi-0-20eb7e44bc457df80828815924cd508a)
Ant风格路径表达式简介
Ant是比Maven更老的Java构建工具。Ant发明了一种描述文件路径的表达式,大家都习惯称其为Ant风格路径表达式。Jenkins pipeline的很多步骤的参数也会使用此表达式。
Ant路径表达式包括3种通配符。
•?:匹配任何单字符。
•*:匹配0个或者任意数量的字符。
•**:匹配0个或者更多的目录。
我们通过以下例子来学习。
•**/CVS/*:匹配CVS文件夹下的所有文件,CVS文件夹可以在任何层级。
以下路径会被匹配到:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/49_1.jpg?sign=1738866945-OTaMUgFm4GN1UMHt0UcU9Rxv8QkJH5iP-0-cc2ef89666fae475be5e13647f6235ed)
以下foo/bar/部分不会被匹配到:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/49_2.jpg?sign=1738866945-X7ctOYC3JQaqTBNlGo2At1BIWYFj7RTu-0-54aa6b6ff983340943298bb7e6221b90)
• org/apache/jakarta/**:匹配org/apache/jakarta路径下的所有文件。
以下路径会被匹配到:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/49_3.jpg?sign=1738866945-jEbYek8DY6lhitiyrq2WE0ADOeAB5UaQ-0-a18e4f16898d792af58a76c831b76d7c)
以下路径不会被匹配到:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/49_4.jpg?sign=1738866945-XfSYPv8KrlWxMzrGJcIMOIP0FIU9eg1O-0-546068e9edecb58e161ca1e0bcb02426)
• org/apache/**/CVS/*:匹配org/apache路径下的CVS文件夹下的所有文件。CVS文件夹可以在任何层级。
以下路径会被匹配到:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/49_5.jpg?sign=1738866945-tnsOqxRyVsDnh8vHHHl8Dfy1PNdRzcuT-0-467891494b0148e22e71d5a9f1ff96f4)
以下路径不会被匹配到:
![](https://epubservercos.yuewen.com/29EDEB/13898202705417506/epubprivate/OEBPS/Images/49_6.jpg?sign=1738866945-BLp0uyXhYEbRZRFxN1VWoteSNmsO2D1l-0-8ff6b459a646cf080f01bf34b26aeeb6)
•**/test/**:匹配所有路径中含有test的路径。