Skip to content

缓存和 Artifacts

缓存

Jenkins 中的 stashunstash 是 Pipeline 脚本里用于跨阶段(stage)共享文件或目录的机制,通常用来实现构建缓存或者在不同节点间传递构建产物。

stash 更适合流水线内部的缓存/传递,不是专门做长期缓存的。


基本概念

  • stash:将指定的文件/目录暂存起来,保存到 Jenkins 主节点(master)或某个共享存储中,方便后续阶段取用。
  • unstash:将之前 stash 的文件/目录恢复到当前工作空间。

典型用法

假设构建流程有多个阶段,比如:

  • 阶段 1:拉取代码,编译,生成构建产物(例如 jar、编译后的文件)
  • 阶段 2:测试,使用阶段 1 产物
  • 阶段 3:打包、发布

如果每个阶段运行在不同的节点或容器,工作空间是独立的,直接用本地文件路径传递文件不通用。就需要用 stashunstash


具体示例

groovy
pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                // 假设构建产物在 build/output 目录
                sh 'mkdir -p build/output && echo "hello" > build/output/file.txt'

                // 将 build/output 目录里的内容缓存起来,名字叫 my-cache
                stash includes: 'build/output/**', name: 'my-cache'
            }
        }

        stage('Test') {
            steps {
                // 还原之前缓存的构建产物
                unstash 'my-cache'

                // 可以访问 build/output/file.txt
                sh 'cat build/output/file.txt'
            }
        }
    }
}

关键点

  • stash 只能保存工作空间里的文件,路径是相对于工作空间的。
  • stash 默认会打包并传输文件到 Jenkins master,默认限制 100MB,超出可能失败(可调整 Jenkins 配置)。
  • stash 名称(name)必须唯一且方便识别。
  • stashunstash 跨节点或不同 agent 的 pipeline 阶段都能使用,方便实现缓存和文件传递。
  • 多个 stash 可以并存,名称不同。

结合缓存使用

你也可以用 stash/unstash 做编译缓存,比如:

groovy
pipeline {
    agent any

    stages {
        stage('Restore Cache') {
            steps {
                // 尝试还原上一次构建的缓存(如果有)
                script {
                    try {
                        unstash 'build-cache'
                    } catch (err) {
                        echo '没有缓存,跳过'
                    }
                }
            }
        }

        stage('Build') {
            steps {
                sh './build.sh'
                stash includes: 'build/output/**', name: 'build-cache'
            }
        }
    }
}

Artifacts

在 Jenkins 中,如果你想查看某次构建的实际产物(即构建生成的 JAR 包、文件等),可以通过 Artifacts(构建产物) 来访问和确认。

存放构建结果

groovy
steps {
  container('maven') {
    sh "mvn clean package -T 8C -s ${MAVEN_SETTINGS}"
    sh 'pwd'
    script {
      archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true
    }
  }
}

获取构建结果

groovy
stage('服务部署') {
  steps {
    copyArtifacts(
      projectName: env.JOB_NAME,
      selector: [
        $class: 'SpecificBuildSelector',
        buildNumber: "${BUILD_NUMBER}"
      ],
      filter: "**/${JAR_NAME}",
      fingerprintArtifacts: true
    )
    sshagent (credentials: [env.SSH_KEY_ID]) {
      sh """
        scp -o StrictHostKeyChecking=no ${JAR_PATH}/${JAR_NAME} ${SSH_USER}@${SSH_HOST}:${SSH_COPY_PATH}
        ssh -o StrictHostKeyChecking=no ${SSH_USER}@${SSH_HOST} ${RESTART}
      """
    }
  }
}