Jenkins知识梳理(2)

作者:没有四次元口袋的蓝胖

日期:2026-10-10

标签:Jenkins, Pipeline, Jenkinsfile, CICD实战

Jenkins知识梳理(2)

写在前面

上一篇我们把 Jenkins 装好了,也通了 GitLab 集成链路。这篇来写真正干活的部分------Jenkinsfile。

Jenkins Pipeline 是 Jenkins 2.0 之后推出的核心能力,用代码(而不是 Web UI 点击)来定义整个构建、测试、部署流程。这个理念叫 Pipeline as Code------构建流程本身也应该被版本化管理。

本文以一个真实的 Spring Boot 项目为例,从零写一个完整的 Jenkinsfile,覆盖拉代码、编译、测试、打包、部署全流程,并逐步优化到生产可用的水平。


一、Pipeline 基础概念

1.1 Declarative vs Scripted Pipeline

Jenkins 有两种 Pipeline 语法:

类型 语法 特点 推荐度
Declarative 结构化语法,更严格 易读、有校验、支持 Blue Ocean 可视化 ⭐⭐⭐⭐⭐ 推荐
Scripted Groovy 脚本,更灵活 灵活但易写乱、无语法校验 ⭐⭐ 复杂场景备选

本文全部使用 Declarative Pipeline。

1.2 Pipeline 的基本结构

groovy 复制代码
pipeline {
    agent any                    // 在哪执行
    
    environment {                // 环境变量
        APP_NAME = 'my-app'
    }
    
    tools {                      // 工具配置
        maven 'Maven3.8'
        jdk 'JDK17'
    }
    
    options {                    // Pipeline 级别选项
        timeout(time: 30, unit: 'MINUTES')
        timestamps()             // 日志显示时间戳
        buildDiscarder(logRotator(numToKeepStr: '20'))
    }
    
    parameters {                 // 参数化构建
        choice(name: 'DEPLOY_ENV', choices: ['staging', 'production'], description: '部署环境')
    }
    
    stages {                     // 阶段(按顺序执行)
        stage('Build') { ... }
        stage('Test') { ... }
        stage('Deploy') { ... }
    }
    
    post {                       // 后置动作(无论成功失败都执行)
        success { ... }
        failure { ... }
        always { ... }
    }
}

1.3 核心语法元素

元素 说明 示例
agent 指定执行节点 agent any / agent { label 'java' } / agent { docker { image 'maven:3.8' } }
stages 所有阶段的容器 包含多个 stage
stage 一个逻辑阶段 stage('Build') { steps { ... } }
steps 阶段内的具体步骤 sh 'mvn clean compile'
post 后置动作 success {} / failure {} / always {}
environment 环境变量 DB_URL = 'jdbc:mysql://...'
when 条件执行 when { branch 'main' }
parallel 并行执行 同一 stage 内多个子 stage 并行
input 人工审批 input { message '确认部署?' }

二、从零写一个完整的 Jenkinsfile

2.1 项目结构

复制代码
my-spring-boot-project/
├── Jenkinsfile              ← Pipeline 定义文件
├── src/
│   ├── main/java/
│   └── test/java/
├── pom.xml
└── docker/
    └── Dockerfile           ← 构建 Docker 镜像

2.2 第一版:基础构建流程

先写一个能跑通的最小 Pipeline:

groovy 复制代码
pipeline {
    agent any
    
    tools {
        maven 'Maven3.8'
        jdk 'JDK17'
    }
    
    stages {
        stage('拉取代码') {
            steps {
                echo '=== 开始拉取代码 ==='
                checkout scm    // 自动从 SCM 配置中拉取(Pipeline from SCM 模式)
            }
        }
        
        stage('编译') {
            steps {
                echo '=== 开始编译 ==='
                sh 'mvn clean compile -q'
            }
        }
        
        stage('单元测试') {
            steps {
                echo '=== 运行单元测试 ==='
                sh 'mvn test'
            }
        }
        
        stage('打包') {
            steps {
                echo '=== 开始打包 ==='
                sh 'mvn package -DskipTests -q'
            }
        }
    }
    
    post {
        success {
            echo '✅ 构建成功!'
        }
        failure {
            echo '❌ 构建失败,请检查日志'
        }
    }
}

这版能跑通,但还远远不够。 接下来逐步优化。


三、进阶优化

3.1 添加缓存加速

每次构建都重新下载 Maven 依赖太慢了,加缓存:

groovy 复制代码
pipeline {
    agent any
    
    tools {
        maven 'Maven3.8'
        jdk 'JDK17'
    }
    
    environment {
        MAVEN_REPO = "${WORKSPACE}/.m2/repository"
    }
    
    stages {
        stage('编译') {
            steps {
                sh "mvn clean compile -Dmaven.repo.local=${MAVEN_REPO} -q"
            }
        }
        
        stage('单元测试') {
            steps {
                sh "mvn test -Dmaven.repo.local=${MAVEN_REPO}"
            }
            post {
                success {
                    junit 'target/surefire-reports/TEST-*.xml'    // 收集测试报告
                }
            }
        }
        
        stage('打包') {
            steps {
                sh "mvn package -DskipTests -Dmaven.repo.local=${MAVEN_REPO} -q"
            }
            post {
                success {
                    archiveArtifacts artifacts: 'target/*.jar',
                                     fingerprint: true
                }
            }
        }
    }
}

3.2 添加代码质量检查

集成 SonarQube 做代码扫描:

groovy 复制代码
stage('代码质量检查') {
    steps {
        echo '=== SonarQube 扫描 ==='
        withSonarQubeEnv('SonarQube-Server') {
            sh "mvn sonar:sonar \
                -Dsonar.projectKey=${env.JOB_NAME} \
                -Dsonar.projectName=${env.JOB_NAME} \
                -Dmaven.repo.local=${MAVEN_REPO}"
        }
    }
}

3.3 添加 Docker 镜像构建

groovy 复制代码
stage('构建 Docker 镜像') {
    steps {
        echo '=== 构建 Docker 镜像 ==='
        script {
            def imageTag = "${env.BUILD_NUMBER}-${env.GIT_COMMIT?.take(8) ?: 'unknown'}"
            def imageName = "registry.company.com/myapp/${env.JOB_NAME}"
            
            sh """
                docker build \
                    --build-arg JAR_FILE=target/*.jar \
                    -t ${imageName}:${imageTag} \
                    -t ${imageName}:latest \
                    -f docker/Dockerfile .
            """
            
            // 推送到镜像仓库
            docker.withRegistry('https://registry.company.com', 'registry-credentials') {
                sh "docker push ${imageName}:${imageTag}"
                sh "docker push ${imageName}:latest"
            }
        }
    }
}

3.4 添加部署步骤

groovy 复制代码
stage('部署到测试环境') {
    when {
        branch 'main'    // 只在 main 分支部署
    }
    steps {
        echo '=== 部署到测试环境 ==='
        sshagent(['deploy-ssh-key']) {
            sh """
                ssh deploy@test-server << 'EOF'
                    cd /opt/myapp
                    docker pull registry.company.com/myapp/${JOB_NAME}:latest
                    docker-compose up -d
                    echo "部署完成"
                EOF
            """
        }
    }
}

stage('部署到生产环境') {
    when {
        branch 'main'
        expression { params.DEPLOY_ENV == 'production' }
    }
    input {
        message '确认部署到生产环境?'
        ok '确认部署'
        submitter 'admin,tech-lead'    // 只有这些人能审批
    }
    steps {
        echo '=== 部署到生产环境 ==='
        sshagent(['deploy-ssh-key']) {
            sh """
                ssh deploy@prod-server << 'EOF'
                    cd /opt/myapp
                    docker pull registry.company.com/myapp/${JOB_NAME}:latest
                    docker-compose up -d
                    echo "生产部署完成"
                EOF
            """
        }
    }
}

四、完整生产级 Jenkinsfile

把上面的优化整合成一个完整版本:

groovy 复制代码
pipeline {
    agent {
        label 'java'    // 指定在有 java 标签的 Agent 上执行
    }
    
    tools {
        maven 'Maven3.8'
        jdk 'JDK17'
    }
    
    environment {
        APP_NAME     = 'my-spring-app'
        MAVEN_REPO   = "${WORKSPACE}/.m2/repository"
        REGISTRY_URL = 'registry.company.com'
        IMAGE_NAME   = "${REGISTRY_URL}/myapp/${APP_NAME}"
        IMAGE_TAG    = "${BUILD_NUMBER}-${GIT_COMMIT?.take(8) ?: 'latest'}"
    }
    
    options {
        timeout(time: 30, unit: 'MINUTES')
        timestamps()
        buildDiscarder(logRotator(numToKeepStr: '20'))
        disableConcurrentBuilds()    // 禁止并发构建
    }
    
    parameters {
        choice(name: 'DEPLOY_ENV', 
               choices: ['staging', 'production'], 
               description: '选择部署环境')
        booleanParam(name: 'SKIP_TEST', defaultValue: false, description: '是否跳过测试')
    }
    
    stages {
        stage('拉取代码') {
            steps {
                echo "📦 拉取代码 - 分支: ${env.GIT_BRANCH}, 提交: ${env.GIT_COMMIT?.take(8)}"
                checkout scm
            }
        }
        
        stage('编译') {
            steps {
                echo '🔨 编译项目'
                sh "mvn clean compile -Dmaven.repo.local=${MAVEN_REPO} -q"
            }
        }
        
        stage('单元测试') {
            when {
                expression { return !params.SKIP_TEST }
            }
            steps {
                echo '🧪 运行单元测试'
                sh "mvn test -Dmaven.repo.local=${MAVEN_REPO}"
            }
            post {
                success {
                    junit allowEmptyResults: true, 
                          testResults: 'target/surefire-reports/TEST-*.xml'
                }
            }
        }
        
        stage('代码质量检查') {
            when {
                expression { return !params.SKIP_TEST }
            }
            steps {
                echo '🔍 SonarQube 代码扫描'
                withSonarQubeEnv('SonarQube-Server') {
                    sh """
                        mvn sonar:sonar \
                            -Dsonar.projectKey=${APP_NAME} \
                            -Dmaven.repo.local=${MAVEN_REPO}
                    """
                }
            }
        }
        
        stage('打包') {
            steps {
                echo '📦 打包构建'
                sh "mvn package -DskipTests -Dmaven.repo.local=${MAVEN_REPO} -q"
            }
            post {
                success {
                    archiveArtifacts artifacts: 'target/*.jar', 
                                     fingerprint: true,
                                     allowEmptyArchive: false
                }
            }
        }
        
        stage('构建 Docker 镜像') {
            steps {
                echo "🐳 构建镜像: ${IMAGE_NAME}:${IMAGE_TAG}"
                sh """
                    docker build \
                        --build-arg JAR_FILE=target/*.jar \
                        -t ${IMAGE_NAME}:${IMAGE_TAG} \
                        -t ${IMAGE_NAME}:latest \
                        -f docker/Dockerfile .
                """
            }
        }
        
        stage('推送镜像') {
            steps {
                echo "📤 推送镜像到 ${REGISTRY_URL}"
                docker.withRegistry("https://${REGISTRY_URL}", 'registry-credentials') {
                    sh "docker push ${IMAGE_NAME}:${IMAGE_TAG}"
                    sh "docker push ${IMAGE_NAME}:latest"
                }
            }
        }
        
        stage('并行测试与检查') {
            parallel {
                stage('集成测试') {
                    steps {
                        echo '🧪 运行集成测试'
                        sh "mvn verify -Dmaven.repo.local=${MAVEN_REPO} -Pintegration-test"
                    }
                }
                stage('安全扫描') {
                    steps {
                        echo '🔒 安全扫描'
                        sh 'echo "执行安全扫描..."'
                    }
                }
            }
        }
        
        stage('部署到测试环境') {
            when {
                allOf {
                    branch 'main'
                    expression { return params.DEPLOY_ENV == 'staging' }
                }
            }
            steps {
                echo '🚀 部署到测试环境'
                sshagent(['deploy-ssh-key']) {
                    sh """
                        ssh deploy@test-server 'cd /opt/${APP_NAME} && \
                            docker pull ${IMAGE_NAME}:${IMAGE_TAG} && \
                            IMAGE_TAG=${IMAGE_TAG} docker-compose up -d'
                    """
                }
            }
            post {
                success {
                    echo "✅ 测试环境部署完成: http://test.example.com"
                }
            }
        }
        
        stage('部署到生产环境') {
            when {
                allOf {
                    branch 'main'
                    expression { return params.DEPLOY_ENV == 'production' }
                }
            }
            input {
                message "确认部署 ${APP_NAME}:${IMAGE_TAG} 到生产环境?"
                ok '确认部署'
                submitter 'admin,tech-lead'
            }
            steps {
                echo '🚀 部署到生产环境'
                sshagent(['deploy-ssh-key']) {
                    sh """
                        ssh deploy@prod-server 'cd /opt/${APP_NAME} && \
                            docker pull ${IMAGE_NAME}:${IMAGE_TAG} && \
                            IMAGE_TAG=${IMAGE_TAG} docker-compose up -d && \
                            echo "生产部署完成"'
                    """
                }
            }
        }
    }
    
    post {
        success {
            echo "✅ Pipeline 执行成功!"
            emailext subject: "✅ [${JOB_NAME}] #${BUILD_NUMBER} 构建成功",
                     body: """
                     <h3>构建成功</h3>
                     <ul>
                       <li>项目:${JOB_NAME}</li>
                       <li>分支:${GIT_BRANCH}</li>
                       <li>提交:${GIT_COMMIT?.take(8)}</li>
                       <li>镜像:${IMAGE_NAME}:${IMAGE_TAG}</li>
                       <li>环境:${params.DEPLOY_ENV}</li>
                       <li><a href="${BUILD_URL}">查看详情</a></li>
                     </ul>
                     """,
                     to: 'team@company.com',
                     mime type: 'text/html'
        }
        failure {
            echo "❌ Pipeline 执行失败!"
            emailext subject: "❌ [${JOB_NAME}] #${BUILD_NUMBER} 构建失败",
                     body: "构建失败,请尽快排查!<br>日志:${BUILD_URL}console",
                     to: 'team@company.com',
                     mime type: 'text/html'
        }
        aborted {
            echo "⚠️ Pipeline 被中止"
        }
        always {
            echo "🧹 清理工作区"
            cleanWs()
        }
    }
}

五、Pipeline 高级技巧

5.1 共享库(Shared Library)

当多个项目有相似的 Pipeline 逻辑时,可以抽取公共代码到共享库:

复制代码
shared-library/
├── src/
│   └── com/company/
│       └── Utils.groovy
└── vars/
    ├── buildJavaApp.groovy
    ├── deployApp.groovy
    └── notifyTeam.groovy

在 Pipeline 中引用共享库:

groovy 复制代码
@Library('my-shared-library') _

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                buildJavaApp(jdkVersion: '17', mavenVersion: '3.8')
            }
        }
        stage('Deploy') {
            steps {
                deployApp(env: 'staging', imageTag: env.IMAGE_TAG)
            }
        }
    }
    post {
        always {
            notifyTeam()
        }
    }
}

5.2 参数化构建

让每次构建可以传入不同参数:

groovy 复制代码
parameters {
    choice(name: 'DEPLOY_ENV', 
           choices: ['dev', 'staging', 'production'], 
           description: '部署环境')
    string(name: 'VERSION', defaultValue: '', description: '指定版本号')
    booleanParam(name: 'SKIP_TEST', defaultValue: false, description: '跳过测试')
}

在 Jenkins 页面点击 "Build with Parameters" 即可选择参数。

5.3 条件执行(when)

groovy 复制代码
stage('Deploy') {
    when {
        anyOf {
            branch 'main'
            branch 'release/*'
        }
        not {
            changelog '.*\\[skip-ci\\].*'    // 提交信息含 [skip-ci] 则跳过
        }
    }
    steps {
        sh './deploy.sh'
    }
}

常用 when 条件:

条件 说明
branch 'main' 只在 main 分支执行
tag 'v*' 只在 v 开头的 Tag 时执行
expression { ... } 自定义 Groovy 表达式
changeset '**/*.java' 有 Java 文件变更时执行
environment name: 'DEPLOY', value: 'true' 环境变量匹配时执行
allOf { ... } 所有条件都满足
anyOf { ... } 任一条件满足
not { ... } 条件取反

5.4 并行执行(Parallel)

同一个 stage 内可以并行执行多个子 stage:

groovy 复制代码
stage('并行检查') {
    parallel {
        stage('单元测试') {
            steps { sh 'mvn test' }
        }
        stage('代码扫描') {
            steps { sh 'mvn sonar:sonar' }
        }
        stage('安全审计') {
            steps { sh './security-scan.sh' }
        }
    }
}

5.5 人工审批(Input)

生产部署前加一个确认环节:

groovy 复制代码
stage('生产部署确认') {
    input {
        message '确认部署到生产环境?'
        ok '确认部署'
        submitter 'admin,tech-lead'
        parameters {
            string(name: 'DEPLOY_NOTE', defaultValue: '', description: '部署备注')
        }
    }
    steps {
        echo "部署备注: ${params.DEPLOY_NOTE}"
        sh './deploy-prod.sh'
    }
}

5.6 错误处理(try-catch)

groovy 复制代码
stage('Deploy') {
    steps {
        script {
            try {
                sh './deploy.sh'
            } catch (Exception e) {
                echo "部署失败: ${e.message}"
                sh './rollback.sh'    // 自动回滚
                currentBuild.result = 'FAILURE'
                throw e               // 重新抛出,让 Pipeline 标记为失败
            }
        }
    }
}

六、构建 19 次,#19 终于成功------调试之路

实际项目中,Pipeline 很少能一次跑通。分享一个真实的调试过程(项目共构建 19 次,第 19 次才完全成功):

6.1 常见失败原因与解决

构建次数 失败原因 解决方案
#1 Maven 依赖下载超时 配置 Maven 私服(Nexus)或本地缓存
#2 JDK 版本不匹配(用了 JDK 8 编译 JDK 17 的代码) 修改 tools 配置指定 JDK17
#3 单元测试失败(Mock 配置不对) 修复测试用例
#4-5 SSH 连接远程服务器失败 检查凭据配置和网络连通性
#6 Docker build 上下文太大(没写 .dockerignore) 添加 .dockerignore
#7 镜像推送到 Registry 认证失败 检查 registry-credentials 凭据
#8-10 Docker Compose 启动失败(端口冲突/环境变量缺失) 调整 docker-compose.yml
#11-15 各种细节调整(路径、权限、日志级别等) 逐步修复
#16-18 优化 Pipeline(添加缓存、并行、通知) 持续迭代
#19 ✅ 全部通过! 🎉

6.2 调试技巧

groovy 复制代码
// 1. 添加详细日志
echo "当前分支: ${env.GIT_BRANCH}"
echo "当前提交: ${env.GIT_COMMIT}"
echo "工作目录: ${env.WORKSPACE}"

// 2. 打印环境变量(排查变量引用问题)
stage('Debug') {
    steps {
        sh 'env | sort'
    }
}

// 3. 使用 try-catch 定位失败步骤
script {
    try {
        sh 'some-command'
    } catch (e) {
        echo "命令执行失败: ${e.message}"
        sh 'cat /tmp/debug.log'    // 打印调试日志
        throw e
    }
}

// 4. 临时允许失败(先跑通其他步骤)
stage('Flaky Test') {
    steps {
        sh 'mvn test -Dtest=FlakyTest'
    }
    post {
        unstable {
            echo '测试不稳定,暂不阻塞构建'
        }
    }
}

七、Jenkinsfile 最佳实践

7.1 编写规范

原则 说明
Jenkinsfile 放在仓库根目录 和代码一起版本管理
Stage 命名清晰 用中文或有意义的英文,让 Blue Ocean 可视化好看
敏感信息走凭据 绝不硬编码密码、Token
合理设置超时 避免构建卡死占用资源
添加注释 复杂逻辑写清楚注释
限制构建历史 用 buildDiscarder 避免磁盘占满

7.2 安全最佳实践

groovy 复制代码
// ❌ 错误:硬编码密码
sh 'mysql -u root -p123456 -h db-server mydb < init.sql'

// ✅ 正确:使用凭据
withCredentials([usernamePassword(credentialsId: 'db-cred', 
                                   usernameVariable: 'DB_USER', 
                                   passwordVariable: 'DB_PASS')]) {
    sh "mysql -u ${DB_USER} -p${DB_PASS} -h db-server mydb < init.sql"
}

7.3 性能优化

优化项 方法
Maven 缓存 使用本地仓库路径 -Dmaven.repo.local
并行执行 parallel {} 让无依赖的 stage 同时跑
Docker 层缓存 合理安排 Dockerfile 指令顺序
跳过不必要的步骤 when {} 条件控制
限制并发构建 disableConcurrentBuilds()

八、Dockerfile 配套示例

配合 Jenkinsfile 中的 Docker 构建步骤:

dockerfile 复制代码
# docker/Dockerfile
FROM eclipse-temurin:17-jre-alpine

LABEL maintainer="team@company.com"

# 时区设置
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 创建应用目录
WORKDIR /opt/app

# 构建参数
ARG JAR_FILE
COPY ${JAR_FILE} app.jar

# JVM 参数(可通过环境变量覆盖)
ENV JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC"
ENV SERVER_PORT=8080

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget -qO- http://localhost:${SERVER_PORT}/actuator/health || exit 1

EXPOSE ${SERVER_PORT}

ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar app.jar"]

思维导图速览

复制代码
Jenkins Pipeline 实战
│
├── Pipeline 基础
│   ├── Declarative(推荐) vs Scripted
│   ├── 基本结构:agent → stages → post
│   ├── 核心元素:stage/steps/environment/when/parallel
│   └── Jenkinsfile 放在仓库根目录
│
├── 构建流程(实战链路)
│   ├── 拉取代码(checkout scm)
│   ├── 编译(mvn compile)
│   ├── 单元测试(mvn test + junit 报告)
│   ├── 代码质量(SonarQube 扫描)
│   ├── 打包(mvn package)
│   ├── Docker 构建(docker build)
│   ├── 推送镜像(docker push)
│   └── 部署(SSH → docker-compose)
│
├── 高级技巧
│   ├── 共享库(Shared Library)复用逻辑
│   ├── 参数化构建(choice/string/booleanParam)
│   ├── 条件执行(when:branch/tag/changeset/expression)
│   ├── 并行执行(parallel 子 stage)
│   ├── 人工审批(input + submitter)
│   └── 错误处理(try-catch + 自动回滚)
│
├── 调试经验
│   ├── 添加 echo 日志
│   ├── 打印环境变量排查
│   ├── try-catch 定位失败步骤
│   ├── allow_failure 临时跳过
│   └── 构建19次才成功是常态,别灰心
│
├── 最佳实践
│   ├── Pipeline as Code(Jenkinsfile 版本管理)
│   ├── 敏感信息走 Credentials
│   ├── 合理设置超时和构建历史
│   └── 性能优化(缓存/并行/跳过/限并发)
│
└── 配套 Dockerfile
    ├── 基础镜像选择(JRE Alpine 更轻量)
    ├── 时区设置
    ├── JVM 参数可配置
    └── 健康检查(HEALTHCHECK)

写在最后

Jenkins Pipeline 的核心思想就一个------Pipeline as Code。

构建流程不是 Web UI 上的点点点,而是写在 Jenkinsfile 里的代码。这意味着:

  • 构建流程可以被 Review(和代码一起 Review)
  • 构建流程可以被版本管理(改坏了能回退)
  • 构建流程可以被复用(共享库机制)

面试中怎么聊 Jenkins?

  1. "我配置了 Jenkins CI/CD 流水线,Pipeline as Code,用 Jenkinsfile 管理构建流程"
  2. "集成了 GitLab Webhook,代码 push 后自动触发构建"
  3. "Pipeline 覆盖编译→测试→代码扫描→打包→Docker 构建→部署全流程"
  4. "生产部署前有人工审批环节,支持一键回滚"
  5. "项目迭代了 19 个版本,从 #1 到 #19 逐步跑通了整条 GitLab + Jenkins 集成链路"

到这里,Git + GitLab + Jenkins 三个模块就全部完成了。从版本控制到协作平台到自动化流水线,一套完整的 DevOps 工具链。

相关推荐
yumgpkpm1 小时前
Acceldata ODP 3.3.6.4 vs CDP Private Cloud Base 7.3.2 对比
大数据·运维·服务器·hadoop·华为·zookeeper·hbase
Liuqy-051 小时前
特殊进程——孤儿、僵尸、守护进程
linux·运维·服务器
考研保研资料分享2 小时前
自动化控制保研经验合辑:上交夏令营、北工大预推免与跨专业面试复盘(2025)
运维·面试·自动化
乐维_lwops3 小时前
2026选择运维监控系统时应该重点考察哪些功能?
大数据·运维·人工智能
峥无3 小时前
Linux NPTL线程:创建/终止/等待/分离/栈布局内核原理|线程下篇
linux·运维·线程
元岳数字人小元3 小时前
数字人私有化部署:企业级AI数字场景长效落地优选方案
运维·人工智能·开源·人机交互·交互
Thneonl4 小时前
全集群钟差 300 毫秒会发生什么:证书悄悄过期,日志倒流
运维·后端
是jin奥4 小时前
Ubuntu 访问 Windows 共享目录
linux·运维·ubuntu