1. 简介
Jenkins 是一个广泛使用的自动化服务器,它帮助我们更高效地构建、测试和部署应用程序。其中,Jenkins Pipeline(流水线) 是其核心功能之一,它允许我们通过脚本定义构建流程。在某些场景下,我们可能需要在继续执行后续步骤之前确认某个文件是否存在。例如:
- 仅当某个文件存在时才发布构建产物(Artifacts)
- 如果文件缺失,跳过某些构建步骤
本文将介绍几种在 Jenkins Pipeline 中检查文件是否存在的方法,涵盖 Declarative Pipeline 和 Scripted Pipeline 两种风格,并结合实际使用场景给出示例。最终我们将看到如何通过文件检查来控制流水线流程。
2. Jenkins Pipeline 基础知识
Jenkins Pipeline 主要分为两种写法:
Declarative Pipeline(声明式流水线)
- 使用特定的语法结构,以
pipeline
块为起点 - 更强调可读性和简洁性
- 适合大多数简单清晰的流水线需求
Scripted Pipeline(脚本式流水线)
- 基于 Groovy 的 DSL(领域特定语言)
- 支持更复杂的逻辑结构,如循环、条件判断等
- 适合需要精细控制或高级脚本的场景
无论使用哪种方式,Pipeline 的底层运行环境是 Groovy,因此我们可以借助 Groovy 方法、Jenkins 提供的 Pipeline 步骤或系统命令来实现文件检查。
3. 检查文件是否存在的方法
3.1 使用 Jenkins Pipeline 步骤
Jenkins 提供了一个内置步骤 fileExists
,用于判断文件是否存在。它接收一个文件路径作为参数,并返回布尔值。
示例:Scripted Pipeline
node {
stage('Check File') {
if (fileExists('myfile.txt')) {
echo "文件存在。"
} else {
echo "文件不存在。"
}
}
}
这段代码运行在 Jenkins Agent 上,检查当前工作目录下是否存在 myfile.txt
文件。如果存在则输出“文件存在”,否则输出“文件不存在”。
3.2 使用 Shell 命令检查文件
有时候我们可能更倾向于使用系统命令来检查文件是否存在。这在 Jenkins 中也可以通过 sh
(Linux/macOS)或 bat
(Windows)步骤实现。
示例:Linux/macOS
node {
stage('Shell Check') {
def result = sh script: '[ -f myfile.txt ] && echo "YES" || echo "NO"', returnStdout: true
if (result.trim() == "YES") {
echo "myfile.txt 存在。"
} else {
echo "myfile.txt 不存在。"
}
}
}
这里我们使用了 shell 命令 [ -f myfile.txt ]
来判断文件是否存在,并通过 returnStdout: true
获取命令输出结果。
示例:Windows
node {
stage('Batch Check') {
def result = bat script: 'if exist myfile.txt (echo YES) else (echo NO)', returnStdout: true
if (result.trim().contains("YES")) {
echo "myfile.txt 存在(Windows)。"
} else {
echo "myfile.txt 不存在(Windows)。"
}
}
}
使用 if exist
命令判断文件是否存在,逻辑类似。
4. 在 Declarative Pipeline 中检查文件
在声明式流水线中,我们依然可以使用 fileExists
或 sh
/bat
步骤。只需要在 steps
中嵌入 script
块即可。
示例:Declarative Pipeline
pipeline {
agent any
stages {
stage('Check File Declarative') {
steps {
script {
if (fileExists('myfile.txt')) {
echo "找到 myfile.txt!"
} else {
echo "未找到 myfile.txt。"
}
}
}
}
}
}
通过 script
块,我们可以在 Declarative Pipeline 中嵌入 Groovy 逻辑,实现动态判断。
5. 处理检查结果
一旦我们确认文件是否存在,就可以根据结果做出不同处理。以下是几种常见做法:
5.1 跳过阶段
例如,我们只想在 deploy-package.zip
存在时才执行部署阶段:
stage('Check for Package') {
steps {
script {
if (!fileExists('deploy-package.zip')) {
error "部署包未找到,终止构建。"
}
}
}
}
如果文件不存在,调用 error
会终止整个流水线。
5.2 标记构建状态为不稳定
如果我们允许流水线继续执行,但希望标记构建为不稳定状态:
script {
if (!fileExists('optional-report.txt')) {
currentBuild.result = 'UNSTABLE'
echo "optional-report.txt 缺失,标记为不稳定。"
}
}
这样流水线仍会完成,但 Jenkins 会记录为 UNSTABLE
状态。
6. 使用共享库(Shared Library)
在大型 Jenkins 项目中,我们通常会使用 Shared Library 来统一和复用代码逻辑。例如我们可以定义一个通用的 checkFileExists
方法:
定义共享库函数(vars/checkFileExists.groovy
)
def call(String filePath) {
return fileExists(filePath)
}
在流水线中使用
@Library('my-shared-lib') _
pipeline {
agent any
stages {
stage('Shared Library Check') {
steps {
script {
if (checkFileExists('somefile.txt')) {
echo "somefile.txt 存在。"
} else {
echo "somefile.txt 不存在。"
}
}
}
}
}
}
这样可以统一文件检查逻辑,提高可维护性。
7. 检查远程服务器上的文件
如果文件位于远程服务器上,我们需要采取额外的步骤:
方法一:先将文件复制到本地工作区
使用 scp
或其他方式将文件拉取到本地,再使用 fileExists
判断。
方法二:直接在远程执行检查
使用 sh
执行 SSH 命令检查远程文件是否存在:
node('myAgentWithSSH') {
stage('Remote File Check') {
sh '''
ssh user@remoteserver "[ -f /path/to/file.txt ] && echo 'YES' || echo 'NO'"
'''
}
}
然后根据输出判断文件是否存在。
⚠️ 注意:远程执行需要提前配置好 SSH 密钥或凭据。
8. 实用技巧
✅ 在检查文件时,以下技巧可提高效率和准确性:
- 使用
echo "当前工作目录: ${pwd()}"
查看当前路径,避免路径错误 - 使用
dir('subfolder')
切换工作目录时,注意文件路径的相对变化 - 并行构建时,不同 Agent 的工作目录相互独立,需确保文件在正确的节点上
- 对于关键文件缺失,使用
error
终止流程;非关键文件可用echo
输出警告
9. 综合示例:条件化归档与部署
下面是一个完整的流水线示例,结合了构建、归档和部署阶段的条件判断:
pipeline {
agent any
stages {
stage('Build') {
steps {
sh "touch build-output.jar"
echo "构建完成。"
}
}
stage('Archive Output') {
steps {
script {
if (fileExists('build-output.jar')) {
echo "归档 build-output.jar..."
archiveArtifacts artifacts: 'build-output.jar', fingerprint: true
} else {
echo "没有可归档的文件。"
}
}
}
}
stage('Deployment Decision') {
steps {
script {
if (fileExists('build-output.jar')) {
echo "开始部署..."
// 部署步骤
} else {
echo "跳过部署,build-output.jar 不存在。"
}
}
}
}
}
}
这个流水线演示了如何根据文件是否存在来决定是否归档和部署,是一种常见的实际应用场景。
10. 小结
在 Jenkins Pipeline 中检查文件是否存在是一个常见需求,尤其在构建、部署和归档阶段。我们可以通过以下方式实现:
- 使用 Jenkins 内置的
fileExists
步骤 - 调用 Shell 或 Batch 命令
- 在 Declarative 和 Scripted Pipeline 中灵活使用
script
块 - 结合 Shared Library 提高复用性
- 远程文件可通过 SSH 或文件传输方式处理
通过这些方法,我们可以灵活控制流水线流程,提升构建和部署的健壮性与可控性。完整示例可在 GitHub 仓库 中查看。