You need to enable JavaScript to run this app. Jenkins声明式定时备份流水线如何实现作业停止后独占运行
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins声明式定时备份流水线如何实现作业停止后独占运行

Jenkins声明式备份流水线独占执行实现方案

实现逻辑

  • 利用Jenkins原生*静默模式(Quiet Mode)*特性:开启后不会调度任何新的构建任务,现有运行中的任务可正常执行完成
  • 流水线启动后先开启静默模式,再等待所有非自身的运行中任务执行结束,再执行备份操作
  • 备份完成后无论执行结果成功/失败,强制关闭静默模式恢复Jenkins正常调度能力

修改后的完整Jenkinsfile

import jenkins.model.Jenkins

def BACKUP_DATETIME = new Date().format('yyyy_MM_dd_HH_mm_ss', TimeZone.getTimeZone('Canada/Eastern'))

pipeline {
    agent { label 'master' }
    options {
        //Build options
        disableResume()
        disableConcurrentBuilds()
        // 可选配置:最多等待1小时,避免异常情况下无限阻塞
        timeout(time: 1, unit: 'HOURS')
        buildDiscarder(
          logRotator (
                       artifactDaysToKeepStr: '10',
                       artifactNumToKeepStr: '1',
                       daysToKeepStr: '30',
                       numToKeepStr: '30'
                     )
        )
    }
    triggers { cron('TZ=Canada/Eastern\n0 3 * * *') }
    environment {
        GIT_SSH_KEY_ID = 'gitlab_builduser'
        BACKUP_PREFIX_NAME = 'jenkins-back-'
        BACKUP_REPO_NAME = "jenkins_backups"
        BACKUP_REPO_URL = "git@XXX:XX/${env.BACKUP_REPO_NAME}.git"
        NUMBER_OF_BACKUPS = '7'
        GOOGLE_CHAT_TOKEN = 'XXXXXF'
        JENKINS_VERSION = ''
    }
    stages {
        // 新增前置检查阶段
        stage('Pre Check') {
            steps {
                script {
                    // 开启全局静默模式,阻止新作业调度
                    Jenkins.instance.doQuietDown()
                    // 循环等待所有非当前备份作业的运行中任务结束
                    while (true) {
                        def runningJobs = Jenkins.instance.getAllItems(Job.class).collectMany { job ->
                            job.getBuilds().findAll { build -> build.isBuilding() }
                        }.findAll { build -> build.getFullDisplayName() != currentBuild.getFullDisplayName() }
                        if (runningJobs.isEmpty()) {
                            break
                        }
                        println "等待以下运行中任务结束:${runningJobs*.getFullDisplayName()}"
                        sleep 30 // 每30秒检测一次
                    }
                }
            }
        }
        stage('Init') {
            steps {
                script {
                    env.JENKINS_VERSION = sh(script: "java -jar /usr/share/jenkins/jenkins.war --version", returnStdout: true).trim()
                }
                dir("/tmp") {
                  withCredentials([sshUserPrivateKey(credentialsId: "${env.GIT_SSH_KEY_ID}", keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER')]) {
                    withEnv(["GIT_SSH_COMMAND=ssh -i ${SSH_KEY}"]) {
                        sh '''
                          if [ ! -d ${BACKUP_REPO_NAME} ]
                          then
                            git clone ${BACKUP_REPO_URL}
                          else
                            cd ${BACKUP_REPO_NAME}
                            git fetch origin
                            git reset --hard origin/master
                          fi
                        '''
                    }
                  }
                }
            }
        }
        stage('Backup') {
            steps {
                dir ('jenkins_backup') {
                  sh """
                    chmod +x ./jenkins-backup.sh
                    ./jenkins-backup.sh ${JENKINS_HOME} /tmp/${env.BACKUP_REPO_NAME}/${BACKUP_PREFIX_NAME}_${BACKUP_DATETIME}.tar.gz
                  """
                }
            }
        }
        stage('Upload') {
            steps {
                // TO_DO: SAVE THE BACKUP file
                dir("/tmp/${env.BACKUP_REPO_NAME}") {
                  withCredentials([sshUserPrivateKey(credentialsId: "${env.GIT_SSH_KEY_ID}", keyFileVariable: 'SSH_KEY', usernameVariable: 'SSH_USER')]) {
                    withEnv(["GIT_SSH_COMMAND=ssh -i ${SSH_KEY}"]) {
                        sh '''
                          git config user.email "${SSH_USER}@email.com"
                          git config user.name "${SSH_USER}"
                          # backup only keep the lastest X backup-files
                          ls -tp ${BACKUP_PREFIX_NAME}_*.tar.gz | grep -v '/$' | tail -n +$(expr ${NUMBER_OF_BACKUPS} + 1) | xargs -I {} rm -- {}
                          # Push to git
                          git add --all
                          git status
                          git commit --amend -CHEAD --allow-empty
                          git push --force-with-lease origin master
                          env
                        '''
                    }
                  }
                }

            }
        }
    }
    post {
        always {
            script {
                // 无论备份结果如何,强制关闭静默模式恢复正常调度
                if (Jenkins.instance.isQuietingDown()) {
                    Jenkins.instance.doCancelQuietDown()
                }
            }
        }
        failure {
          hangoutsNotify message: "${JOB_BASE_NAME} faild!",token: "${env.GOOGLE_CHAT_TOKEN}",threadByJob: true
        }
    }
}

注意事项

  • 运行该流水线的账号需要拥有Jenkins管理员权限,否则无法操作静默模式和查询全局任务状态
  • 静默模式开启后,用户手动触发的作业也会进入排队状态,等静默模式关闭后自动调度,对多Agent节点集群同样生效

内容的提问来源于stack exchange,提问作者Taher Ben Salem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 14:24:03