云计算百科
云计算领域专业知识百科平台

Jenkins 构建历史管理与磁盘清理全攻略:5步根治服务器磁盘爆满

Jenkins 构建历史管理与磁盘清理全攻略:5步根治服务器磁盘爆满

      • 📈 构建历史管理全景流程图
      • 一、核心概念:构建历史到底占用了哪些空间?
        • 1. 构建历史的存储结构
        • 2. 磁盘空间占用分析
      • 二、策略一:全局自动清理配置(最基础)
        • 操作步骤
      • 三、策略二:Job 级别的丢弃策略(最常用)
        • 操作步骤
      • 四、策略三:Pipeline 中主动清理(最灵活)
        • 1. 清理工作空间
        • 2. 归档产物按需清理
        • 3. 使用 buildDiscarder 属性(脚本式Pipeline)
      • 五、策略四:脚本批量清理(应急救火)
        • 1. Groovy脚本(在Jenkins Script Console中执行)
        • 2. Shell脚本(直接在服务器执行)
      • 六、监控体系:从被动清理到主动预警
        • 1. 安装磁盘监控插件
        • 2. 配置磁盘阈值告警
        • 3. 定期巡检Pipeline
      • 📊 四种清理策略对比
      • 📚 常见问题排查
      • 💎 总结

🌺The Begin🌺点点关注,收藏不迷路🌺

⬇ ⬇ 底部 ⬇ ⬇


你是否遇到过这样的场景:Jenkins运行了半年后,服务器磁盘突然告警,登录一看,jobs 目录占用了上百GB空间——几万次的历史构建、几百G的归档产物,让服务器不堪重负。构建历史管理就是解决这一问题的系统性方案。

📈 构建历史管理全景流程图

先通过一张图理解构建历史从产生到清理的完整生命周期:

#mermaid-svg-SBQ1dQEmwhU2Zhl5{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .error-icon{fill:#552222;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .marker.cross{stroke:#333333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 p{margin:0;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .cluster-label text{fill:#333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .cluster-label span{color:#333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .cluster-label span p{background-color:transparent;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .label text,#mermaid-svg-SBQ1dQEmwhU2Zhl5 span{fill:#333;color:#333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node rect,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node circle,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node ellipse,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node polygon,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .rough-node .label text,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node .label text,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .image-shape .label,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .rough-node .label,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node .label,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .image-shape .label,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .icon-shape .label{text-align:center;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node.clickable{cursor:pointer;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .arrowheadPath{fill:#333333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .cluster text{fill:#333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .cluster span{color:#333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .icon-shape,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .icon-shape p,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .icon-shape .label rect,#mermaid-svg-SBQ1dQEmwhU2Zhl5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SBQ1dQEmwhU2Zhl5 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

定期执行

⚙️ 每次Pipeline执行

📦 生成构建记录

存储内容

📋 构建日志log文件

📦 归档产物artifacts

📊 JUnit测试报告

💾 工作空间快照

存储于 $JENKINS_HOME/jobs/

管理策略

策略1: 全局自动清理配置

策略2: Job级别丢弃策略

策略3: Pipeline中清理

策略4: 脚本批量删除

🗑️ 清理过期构建

✅ 释放磁盘空间

📊 监控 + 告警

核心逻辑: 构建历史管理是一个闭环——清理不是目的,建立自动化的清理策略 + 监控告警才是根本。


一、核心概念:构建历史到底占用了哪些空间?

在动手清理之前,必须搞清楚Jenkins到底把数据存在哪里、存了什么。

1. 构建历史的存储结构

Jenkins构建数据存储路径:

$JENKINS_HOME/jobs/
├── project-A/
│ ├── builds/
│ │ ├── 1/ # 第1次构建
│ │ │ ├── log # 构建日志
│ │ │ ├── archive/ # 归档产物(jar包等)
│ │ │ ├── junitResult.xml # 测试报告
│ │ │ └── build.xml # 构建元数据
│ │ ├── 2/ # 第2次构建
│ │ └── ...
│ ├── workspace/ # 工作空间(可能很大)
│ └── config.xml # Job配置
└── project-B/
└── ...

2. 磁盘空间占用分析
存储内容磁盘占用比例清理优先级
归档产物(Artifacts) 40-60% ⭐⭐⭐⭐⭐ 最高
工作空间(Workspace) 20-30% ⭐⭐⭐⭐
构建日志(Logs) 10-15% ⭐⭐⭐
测试报告(Reports) 5-10% ⭐⭐
构建元数据(XML) 1-5% ⭐(不建议清理)

关键认知: 归档产物(Artifacts)和工作空间(Workspace)是最大的磁盘消耗者,应作为清理的重点目标。


二、策略一:全局自动清理配置(最基础)

这是Jenkins内置的**全局兜底策略**,对所有Job生效。

操作步骤
  • 登录Jenkins,进入 Manage Jenkins → System
  • 找到 Global Build Discarders 部分。
  • 勾选并配置清理策略。
  • 推荐配置:

    策略类型:Log Rotation
    保留天数:30天
    保留最大构建数:50

    注意:

    • 这个配置是全局默认值,每个Job可以独立覆盖。
    • 建议设置得宽松一些(如保留30天),然后在个别高频Job上单独收紧。

    三、策略二:Job 级别的丢弃策略(最常用)

    对于每天构建几十次的高频项目,需要在Job级别设置更激进的清理策略。

    操作步骤
  • 进入具体Job的 Configure → General
  • 找到 Discard old builds(丢弃旧的构建)。
  • 配置以下参数:
  • 策略配置说明:

    参数推荐值(高频Job)推荐值(低频Job)说明
    Days to keep builds 7天 30天 按时间保留
    Max # of builds to keep 20次 50次 按数量保留
    Days to keep artifacts 3天 14天 产物保留时长(可短于构建保留)
    Max # of builds with artifacts 5次 20次 只保留最近N次的产物

    工作机制: 两个条件以**先满足者为准**。例如同时设置"保留7天"和"保留20次",某天第21次构建成功时,即使它只过了1天,最老的第1次也会被清理。

    最佳实践:

    • 归档产物(Artifacts)的保留时长应短于构建记录。
    • 生产发布Job的构建历史建议永久保留(不设置丢弃策略)。
    • 特性分支Job建议保留5次以内。

    四、策略三:Pipeline 中主动清理(最灵活)

    在Pipeline脚本中,可以精确控制构建结束后清理哪些内容。

    1. 清理工作空间

    声明式Pipeline示例:

    pipeline {
    agent any

    stages {
    stage('Build') {
    steps {
    sh 'mvn clean package'
    }
    }
    }

    post {
    always {
    // 方法1:使用cleanWs插件清理工作空间
    cleanWs(
    cleanWhenAborted: true,
    cleanWhenFailure: true,
    cleanWhenNotBuilt: true,
    cleanWhenUnstable: true,
    deleteDirs: true,
    patterns: [
    [pattern: 'target/', type: 'INCLUDE'],
    [pattern: 'node_modules/', type: 'INCLUDE']
    ]
    )

    // 方法2:直接删除目录
    // deleteDir()
    }
    }
    }

    2. 归档产物按需清理

    pipeline {
    agent any

    stages {
    stage('Archive') {
    steps {
    // 仅归档重要产物
    archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
    }
    }
    }

    post {
    always {
    // 清理构建过程中产生的临时文件
    sh '''
    rm -rf target/tmp/
    rm -rf target/*-sources.jar
    '''

    }
    }
    }

    3. 使用 buildDiscarder 属性(脚本式Pipeline)

    properties([
    buildDiscarder(
    logRotator(
    artifactDaysToKeepStr: '3',
    artifactNumToKeepStr: '10',
    daysToKeepStr: '7',
    numToKeepStr: '30'
    )
    )
    ])

    node {
    stage('Build') {
    // 构建逻辑
    }
    }

    优势: 将清理策略代码化,随Jenkinsfile版本控制,团队成员都能看到和修改。


    五、策略四:脚本批量清理(应急救火)

    当磁盘已经爆满,需要**立即释放空间**时,使用脚本批量操作。

    1. Groovy脚本(在Jenkins Script Console中执行)

    进入 Manage Jenkins → Script Console,执行以下脚本:

    批量删除所有Job的旧构建(保留最近10次):

    // 遍历所有Job
    Jenkins.instance.allItems.findAll { it instanceof hudson.model.Job }.each { job ->
    println "清理Job: ${job.fullName}"

    // 获取所有构建记录,按编号倒序排列
    def builds = job.builds.sort { it.number }.reverse()

    // 保留最近10次构建
    def buildsToKeep = 10
    if (builds.size() > buildsToKeep) {
    builds.drop(buildsToKeep).each { build ->
    println " 删除构建 #${build.number}"
    build.delete()
    }
    }
    }
    println "清理完成!"

    仅清理构建产物,保留构建日志:

    Jenkins.instance.allItems.findAll { it instanceof hudson.model.Job }.each { job ->
    println "清理产物: ${job.fullName}"

    job.builds.each { build ->
    // 获取归档产物目录
    def artifactsDir = new File(build.rootDir, 'archive')
    if (artifactsDir.exists()) {
    def size = artifactsDir.directorySize()
    println " 构建 #${build.number} 产物大小: ${size / 1024 / 1024} MB"

    // 删除产物(保留构建记录和日志)
    artifactsDir.deleteDir()
    println " 已删除构建 #${build.number} 的产物"
    }
    }
    }

    查找并清理大文件构建:

    // 查找所有构建,按磁盘占用排序
    def buildSizes = []
    Jenkins.instance.allItems.findAll { it instanceof hudson.model.Job }.each { job ->
    job.builds.each { build ->
    def size = build.rootDir.directorySize()
    buildSizes << [job: job.fullName, number: build.number, sizeMB: size / 1024 / 1024]
    }
    }

    // 按大小降序排列,输出前20个
    buildSizes.sort { it.sizeMB }.take(20).each {
    println "${it.job} – Build #${it.number}: ${it.sizeMB.round(2)} MB"
    }

    2. Shell脚本(直接在服务器执行)

    查找占用最大的Job目录:

    #!/bin/bash
    JENKINS_HOME="/var/lib/jenkins"

    echo "=== Jenkins 磁盘占用 Top 20 ==="
    du -sh $JENKINS_HOME/jobs/*/ | sort -rh | head -20

    echo ""
    echo "=== Workspace 占用 Top 10 ==="
    du -sh $JENKINS_HOME/jobs/*/workspace/ | sort -rh | head -10

    删除所有超过30天的构建产物:

    #!/bin/bash
    JENKINS_HOME="/var/lib/jenkins"
    DAYS_OLD=30

    echo "清理超过 ${DAYS_OLD} 天的构建产物…"

    find $JENKINS_HOME/jobs/*/builds/ -maxdepth 3 -type d -name "archive" -mtime +$DAYS_OLD | while read dir; do
    echo "删除: $dir (大小: $(du -sh $dir | cut -f1))"
    rm -rf "$dir"
    done

    echo "清理完成!"

    ⚠️ 安全警告: 使用Shell脚本前务必:

  • 先备份 $JENKINS_HOME。
  • 在测试环境验证脚本。
  • 确认 find 命令的 -mtime 参数逻辑正确。

  • 六、监控体系:从被动清理到主动预警

    清理只是治标,监控才是治本。

    1. 安装磁盘监控插件

    安装 Disk Usage Plugin

    • 进入 Manage Jenkins → Plugins,搜索安装 Disk Usage。
    • 安装后在 Manage Jenkins 页面看到 Disk Usage 链接。
    • 可视化管理每个Job的磁盘占用。
    2. 配置磁盘阈值告警

    Manage Jenkins → System 中设置:

    磁盘空闲空间告警阈值:10GB
    当低于阈值时:发送邮件通知管理员

    3. 定期巡检Pipeline

    创建一个专门的Jenkins Job,每周执行一次磁盘巡检:

    pipeline {
    agent any

    triggers {
    cron('0 8 * * 1') // 每周一早上8点执行
    }

    stages {
    stage('Check Disk Usage') {
    steps {
    script {
    def jenkinsHome = new File('/var/lib/jenkins')
    def freeSpace = jenkinsHome.freeSpace / 1024 / 1024 / 1024
    def totalSpace = jenkinsHome.totalSpace / 1024 / 1024 / 1024

    echo "Jenkins磁盘总空间: ${totalSpace.round(2)} GB"
    echo "Jenkins磁盘剩余空间: ${freeSpace.round(2)} GB"

    if (freeSpace < 10) {
    emailext(
    subject: "🚨 Jenkins磁盘空间不足告警",
    body: "剩余空间: ${freeSpace.round(2)} GB,请立即清理!",
    to: 'admin@company.com'
    )
    error "磁盘空间不足,巡检失败!"
    }
    }
    }
    }

    stage('Clean Old Workspaces') {
    steps {
    sh '''
    find /var/lib/jenkins/jobs/*/workspace/ \\
    -maxdepth 0 \\
    -type d \\
    -mtime +14 \\
    -exec rm -rf {} \\\\;
    '''

    }
    }
    }
    }


    📊 四种清理策略对比

    策略适用场景粒度优点缺点
    全局配置 兜底策略 全局 简单、一劳永逸 无法差异化处理
    Job级别 日常管理 Job级 灵活、精细 需逐个配置
    Pipeline中 代码化团队协作 构建级 可版本控制、精确 需要编码能力
    脚本批量 应急救火 无限制 快速、强力 风险高、不可逆

    📚 常见问题排查

    问题原因解决方案
    设置了丢弃策略但没生效 旧策略与新策略冲突 手动删除一次旧构建,后续自动策略生效
    Pipeline脚本清理失败 Jenkins用户无删除权限 确认Jenkins进程用户对 jobs/ 目录有写权限
    清理后磁盘空间未释放 删除的文件仍被进程占用 重启Jenkins服务或使用 lsof 检查占用
    构建历史被误删 脚本参数过大 提前备份,使用更保守的保留数量

    💎 总结

    通过本文,你已建立完整的Jenkins构建历史管理知识体系:

  • 四层清理策略:全局配置 → Job级别 → Pipeline脚本 → 应急脚本。
  • 空间占用大头:归档产物(40-60%)和工作空间(20-30%)应优先清理。
  • 保留原则:构建日志保留时间 > 归档产物保留时间;生产Job永久保留。
  • 监控闭环:定期巡检 + 阈值告警,变被动清理为主动预防。
  • 黄金法则: 不要把Jenkins当仓库——构建产物的归宿是Nexus/Artifactory,构建历史的归宿是定期归档,工作空间永远是临时的。做好这三点,你的Jenkins服务器就能长期保持健康状态。

    在这里插入图片描述

    🌺The End🌺点点关注,收藏不迷路🌺

    ⬆ ⬆ 顶部 ⬆ ⬆

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Jenkins 构建历史管理与磁盘清理全攻略:5步根治服务器磁盘爆满
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!