[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"categories":3,"article-18":51,"comments-18":96},[4,10,16,22,28,34,40,46],{"_id":5,"id":6,"created_at":7,"updated_at":7,"name":8,"description":8,"cover":9},"6a294c7a9fbda20eb7c62dd5",1,"2022-12-08T13:59:08.000Z","域.业务领域","\u002Fblog\u002Flighthouse.jpeg",{"_id":11,"id":12,"created_at":13,"updated_at":14,"name":15,"description":15,"cover":9},"6a294c7a9fbda20eb7c62dd6",2,"2022-12-08T13:59:56.000Z","2022-12-08T14:02:20.000Z","术.解决方案",{"_id":17,"id":18,"created_at":19,"updated_at":20,"name":21,"description":21,"cover":9},"6a294c7a9fbda20eb7c62dd7",3,"2022-12-08T14:00:22.000Z","2022-12-08T14:02:17.000Z","技.技术研究",{"_id":23,"id":24,"created_at":25,"updated_at":26,"name":27,"description":27,"cover":9},"6a294c7a9fbda20eb7c62dd8",4,"2022-12-08T14:00:33.000Z","2022-12-08T14:02:14.000Z","阵.技术应用",{"_id":29,"id":30,"created_at":31,"updated_at":32,"name":33,"description":33,"cover":9},"6a294c7a9fbda20eb7c62dd9",5,"2022-12-08T14:01:04.000Z","2022-12-08T14:02:12.000Z","法.手段方法 ",{"_id":35,"id":36,"created_at":37,"updated_at":38,"name":39,"description":39,"cover":9},"6a294c7a9fbda20eb7c62dda",6,"2022-12-08T14:01:15.000Z","2022-12-08T14:02:09.000Z","理.理论学习",{"_id":41,"id":42,"created_at":43,"updated_at":44,"name":45,"description":45,"cover":9},"6a294c7a9fbda20eb7c62ddb",7,"2022-12-08T14:01:24.000Z","2022-12-08T14:02:06.000Z","器.工具使用",{"_id":47,"id":48,"created_at":49,"updated_at":49,"name":50,"description":50,"cover":9},"6a294c7a9fbda20eb7c62ddc",8,"2022-12-08T14:01:53.000Z","杂.杂七杂八",{"_id":52,"id":53,"created_at":54,"updated_at":55,"title":56,"content":57,"description":58,"cover":59,"created_date":60,"category_id":42,"tag_ids":61,"author_ids":62,"public":6,"status":6,"star":12,"like":6,"views":63,"category":64,"tags":65,"authors":78,"related":85},"6a294c7a9fbda20eb7c62e12",18,"2023-02-06T13:40:31.000Z","2026-06-13T09:51:57.992Z","Jenkins 不完全指南","# Jenkins 不完全指南\n## Jenkins 是什么?\nJenkins 是一款由 Java 编写的开源的``持续集成工具(ci\u002Fcd)``\n\n## Jenkins 的安装\n> CentOS7 以下可以直接使用 yum 安装\n\n> Centos8 及以上可以使用 dnf 安装，将 yum 命令替换为 dnf 命令即可；没有dnf 可以自行安装 ``yum install dnf``\n\n> Jenkins 依赖 ``java`` 环境，请确保已安装 ``java``, 在终端输入 ``java`` 敲击回车验证\n\n* yum 源导入\n```sh\n#添加Yum源\nsudo wget -O \u002Fetc\u002Fyum.repos.d\u002Fjenkins.repo https:\u002F\u002Fpkg.jenkins.io\u002Fredhat-stable\u002Fjenkins.repo\n\n#导入密钥\nsudo rpm --import https:\u002F\u002Fpkg.jenkins.io\u002Fredhat-stable\u002Fjenkins.io.key\n```\n* 安装\u002F卸载\n```sh\n# 升级 yum 源中的所有包\nsudo yum upgrade\n\n#安装\nsudo yum install jenkins\n\n#卸载\nyum remove jenkins\n\n#想卸干净点，执行下面命令\nrm -rf \u002Fetc\u002Fsysconfig\u002Fjenkins.rpmsave\nrm -rf \u002Fvar\u002Fcache\u002Fjenkins\u002F\nrm -rf \u002Fvar\u002Flib\u002Fjenkins\u002F\nrm -rf \u002Fvar\u002Flog\u002Fjenkins\nrm -rf \u002Fusr\u002Flib\u002Fjenkins\n```\n\n## Jenkins 的启动\u002F重启\u002F停止\u002F状态\n```sh\n# 启动 Jenkins 服务\nsystemctl start jenkins\n# 重启 Jenkins 服务\nsystemctl restart jenkins\n# 停止 Jenkins 服务\nsystemctl stop jenkins\n# 查看 Jenkins 服务状态\nsystemctl status jenkins\n```\nJenkins 运行在机器的 ``8080`` 端口，使用云服务器的同学记得到防火墙放行端口。\n\n## 初始化 Jenkins\n在浏览器输入 ``http:\u002F\u002F\u003C你的服务器 IP>:8080`` 就可以访问到 Jenkins 的解锁界面了。\n\n首次进入初始化 Jenkins 需要输入一段命令来查看密码，在服务器终端执行：\n```sh\ncat \u002Fvar\u002Flib\u002Fjenkins\u002Fsecrets\u002FinitialAdminPassword\n```\n把控制台输出的密码复制到 Jenkins 解锁界面中，就到插件安装界面了\n\n## 安装插件\n> 我们选择左边的默认安装推荐插件，然后静等插件安装完成。\n### 假如插件安装失败，不要慌，我们分析下情况（欢迎大家补充）\n* 被墙了\n    1. 尝试开启科学上网（``推荐``）\n    2. 换源，这里推荐清华源\n* 操作不对\n    1. 点击重试，一般多试几次就可以\n    2. 重新阅读本教程一遍\n    3. 卸载 jenkins，重新把安装流程走一边\n    4. [手动下载插件](http:\u002F\u002Fupdates.jenkins-ci.org\u002Fdownload\u002Fplugins\u002F)\n    5. 重启服务器\n\n## 创建用户\n安装成功之后，根据提示创建管理员用户，到此，我们的Jenkins就安装成功了，也创建了我们自己的管理员账户\n\n## 新建任务\n> 本教程不赘述自由风格（Freestyle project）软件项目，因太过简单，教程烂大街\n\n现在我们可以新建任务了，点击主界面左侧的新建任务，选择构建一个流水线（Pipeline）软件项目，给任务取个名字\n\n## Jenkins Pipeline 是什么?（大概看看，不懂可以跳过，因为我也不太懂）\nJenkins Pipeline（或简称为 \"Pipeline\"）是一套插件，将持续交付的实现和实施集成到 Jenkins 中。持续交付 Pipeline 自动化的表达了这样一种流程：将基于版本控制管理的软件持续的交付到您的用户和消费者手中。\tJenkins Pipeline 提供了一套可扩展的工具，用于将“简单到复杂”的交付流程实现为“持续交付即代码”。Jenkins \tPipeline 的定义通常被写入到一个文本文件（称为 Jenkinsfile ）中，``该文件可以被放入项目的源代码控制库中！！厉害吧👍``\n\n## 配置流水线\n### Pipeline 可以两种方式来配置\n> 建议把 ``Jenkinsfile（Pipeline 脚本）`` 跟项目源码一块加入到版本控制中，这样方便项目成员了解构建构建和流程。当然出于安全，有些环境变量和参数等可以管理在 Jenkins 管理平台上，具体后续会有介绍\n\n* 配置 git 仓库的方式来获取到 pipeline 脚本（``推荐``）\n    1. 定义（Definition）选择 Pipeline script from SCM\n    2. SCM 选择 Git\n    3. 配置 Jenkinsfile 所在仓库地址\n    4. 选择 Credentials，添加凭证（``重要``！没有的话配置一下 ``git ssh`` 连接信息）\n    5. 选择脚本路径（``Script Path``）路径（通常默认 Jenkinsfile 即可）\n* 在配置页面直接写 pipeline 脚本\n\n### pipeline 脚本\n\n> 有些插件安装后可以直接在 pipeline 中使用，如发送邮件的 ``Extended E-mail Notification``，安装后可以直接 ``steps { emailext to: 'mafeifan@qq.com', subject: \"test\", body: \"an email\"}`` 来发送邮件\n\n``pipeline`` 能使用 ``Declarative Pipeline（声明式）``、``Scripted Pipeline（脚本化）``两种语法进行编写, 都是使用 ``groovy`` 来实现的\n\n> 推荐使用 ``Declarative Pipeline（声明式）``，也是官方最新推荐的\n\n#### 例：声明式pipeline\n\n```groovy\npipeline {\n  agent any\n   \u002F\u002F stages 包含一个或多个阶段(stage)的容器\n  stages {\n     \u002F\u002F stage 阶段，pipleline流水线由一个或多个阶段(stage)组成，每个阶段必须有名称，这里build就是此阶段的名称\n     stage('build') {\n       \u002F\u002F steps，阶段中的一个或多个具体步骤(step)的容器\n       steps {\n         \u002F\u002F 这是是具体的步骤，真正”做事“的，不可再拆分的最小操作\n         echo \"hello world\"\n       }  \n     }\n  }\n}\n```\n\n* 所有的声明必须包含在 pipeline 语句块中。\n* 块只能由 stage, directives (指令，后续会讲到) 或 steps 组成。\n* agent：指定流水线的执行位置，流水线中的每个阶段都必须在某个地方（物理机，虚拟机或 Docker 容器）执行，agent 部分即指定具体在哪里执行。\n* echo 是内置命令，用来输出一段文本，还有些命令是安装插件后才有的，参见官方文档。\n* step： 步骤，可拆分最小单元，真正“做事”的语句。如 echo \"hello world\" 表示输出一句话。\n\n#### 例：脚本式 pipeline\n\n```groovy\nnode {\n      \u002F* .. snip .. *\u002F\n      withEnv([\"PATH+MAVEN=${tool 'M3'}\u002Fbin\"]) {\n          sh 'mvn -B verify'\n      }\n}\n```\n\n### groovy 是什么\n> Groovy 是用于  Java虚拟机的一种敏捷的动态语言，它是一种成熟的面向对象编程语言，既可以用于面向对象编程，又可以用作纯粹的脚本语言。使用该种语言不必编写过多的代码，同时又具有闭包和动态语言中的其他特性\n\n* 写 pipeline 就是写 Groovy 代码，Jenkins pipeline 其实就是基于 Groovy 语言实现的一种 DSL，了解一些 Groovy 语法知识是很有必要的\n\n* 不想本地安装 Groovy 环境的话，可以打开 [https:\u002F\u002Fgroovy-playground.appspot.com\u002F](groovy-playground) 运行线上 groovy 代码，直接查看结果，该网站可能需要会科学上网\n\n### 必要的 Groovy 语法知识\n* 定义变量和方法用def关键字，def name=\"jack\"\n* 语句最后的分号不是必需的\n* 方法调用时可以省略括号\n\n```groovy\ndef say(String name = \"world\") {\n  return \"hi \" + name\n}\n\u002F\u002F 调用\nsay name = \"jack\"\n```\n\n* 双引号支持插值，单引号不会解析变量，原样输出\n\n```groovy\ndef name = 'world'\n\u002F\u002F 结果： hello world\nprint \"hello ${name}\"\n\u002F\u002F 结果： hello ${name}\nprint 'hello ${name}\n```\n\n* 三双引号和三单引号都支持换行，只有三双引号支持插值\n```groovy\ndef foo = \"\"\" line one\nline two\n${name}\n\"\"\"\n```\n\n* 支持闭包\n```groovy\n\u002F\u002F 定义闭包\ndef codeBlack = {print \"hello closure\"}\n\u002F\u002F 闭包当做函数调用\ncodeBlack\n\u002F\u002F 闭包可以赋值给变量，或者作为参数传递\ndef pipeline(closure) {\n  closure()\n}\npipeline(codeBlack)\n\n\u002F\u002F 因为括号是非必需的，下面几种写法结果是一样的，是不是和 Jenkins pipeline 很像呢\npipeline( {print \"hello closure\"} )\npipeline { \n  print \"hello closure\"\n} \npipeline codeBlack\n```\n\n* 闭包的另一个用法\n```groovy\ndef stage(String name, closure) {\n  println name\n  closure()\n}\n\n\u002F\u002F 正在情况下，我们这样使用stage函数\n\nstage(\"stage name\", {\n   println \"closure\"\n})\n\n\u002F\u002F 最终打印\n\u002F*\nstage name\nclosure\n*\u002F\n\u002F\u002F 但是，在Groovy里，可以直接这么写\n\nstage(\"stage name\") {\n  print \"closure\"\n}\n```\n\n### Jenkins 环境变量\n> 环境变量可以被看作是 pipeline 与 Jenkins 交互的媒介。比如，可以在 pipeline 中通过 BUILD_ NUMBER 变量知道构建任务的当前构建次数。环境变量可以分为 Jenkins 内置变量和自定义变量。\n\n#### Jenkins 内置变量\n\n在 pipeline 执行时，Jenkins 通过一个名为 env 的全局变量，将 Jenkins 内置环境变量暴露出来。其使用方法有多种，示例如下:\n```groovy\npipeline {\n  agent any\n  stages {\n    stage('Example') {\n      steps {\n         echo \"Running ${env.BUILDNUMBER} on ${env.JENKINS_URL}\" # 方法1\n         echo \"Running $env.BUILDNUMBER on $env.JENKINS_URL\"  # 方法2\n         echo \"Running ${BUILDNUMBER} on ${JENKINS_URL}\"   # 方法3 不推荐，难排查\n      }\n    }\n  }\n}\n```\n默认 env 的属性可以直接在 pipeline 中引用。所以以上方法都是合法的。但是不推荐方法三，因为出现变量冲突时，非常难查问题。\n\n通过访问 ``\u003CJenkins master的地址>\u002Fpipeline-syntax\u002Fglobals#env`` 来获取完整列表。在列表中，当一个变量被声明为 ``\"For a multibranch project\"``时，代表只有多分支项目才会有此变量。\n\n实际工作中经常用到的变量:\n* BUILD_ NUMBER：构建号，累加的数字。在打包时，它可作为制品名称的一部分，比如server-2.jar。\n* BRANCH_ NAME：多分支pipeline项目支持。当需要根据不同的分支做不同的事情时就会用到，比如通过代码将release分支发布到生产环境中、master分支发布到测试环境中。\n* BUILD_ URL：当前构建的页面URL。如果构建失败，则需要将失败的构建链接放在邮件通知中，这个链接就可以是BUILD _URL。\n* GIT BRANCH：通过git拉取的源码构建的项目才会有此变量。\n\n在使用 env 变量时，需要注意不同类型的项目，env 变量所包含的属性及其值是不一样的。比如普通 pipeline 任务中的 GIT BRANCH 变量的值为 origin\u002Fmaster，而在多分支 pipeline 任务中 GIT BRANCH 变量的值为 master。\n所以，在 pipeline 中根据分支进行不同行为的逻辑处理时，需要留意。\n\n#### 自定义变量\n\n1. pipeline提供的environment指令中定义\n\n```groovy\npipeline {\n    agent any\n    environment {\n        \u002F\u002F 覆盖默认的PATH变量值\n        PATH=\"\u002Fbin:\u002Fsbin:\u002Fusr\u002Fbin:\u002Fusr\u002Fsbin:\u002Fusr\u002Flocal\u002Fbin\"\n        name='jack'\n    }\n    stages {\n        stage(\"test env\") {\n            steps {\n                sh \"printenv\"  #调试，打印所有env变量\n                echo \"${name}\"  # jack\n                echo \"${env.name}\"  # jack\n            }\n        }\n    }\n}\n```\n\nenvironment指令可以用在pipeline中定义，作用域就是整个pipeline，当定义在stage阶段，只在当前stage有效\n\n2. 环境变量的互相引用\n> 在调试pipeline时，可以再开始阶段加一句 sh 'printenv' 将所有env变量打印出来\n\n> 自定义变量时，为避免命名冲突，可根据项目或公司加上统一前缀，如__server_name，__就是前缀\n\n```groovy\nenvironment {\n    __server_name = 'email-server'\n    __version = \"${BUILD_NUMBER}\"\n    __artifact_name = \"${__server_name}-${__version}.jar\"\n}\n```\n\n3. 自定义全局环境变量 定义全局环境变量可以跨pipeline使用 进入Jenkins -- Manage Jenkins -- 找到Global properties -- 勾选Environment variables\n\n自定义全局环境变量会被加入env属性列表中，所以使用时可以直接用${env.g_name}引用\n\n4. 动态定义变量\n\n```groovy\npipeline {\n    agent any\n    \n    environment {\n       _version = createVersion()\n    }\n    \n    stages {\n        stage ('build') {\n            steps {\n                script {\n                    echo \"${_version}\"\n                }\n            }\n        }\n    }\n}\n\ndef createVersion() {\n    return new Date().format('yyyyMM') + \"-${env.BUILD_NUMBER}\"\n}\n```\n\n### Pipeline 中的指令\n> 显然，基本结构满足不了现实多变的需求。所以，Jenkins pipeline通过各种指令(directive) 来丰富自己。指令可以被理解为对Jenkins pipeline基本结构的补充\n\n* Jenkins pipeline支持的指令有:\n* environment: 用于设置环境变量，可定义在stage或pipeline部分。\n* tools: 可定义在pipeline或stage部分。它会自动下载并安装我们指定的工具，并将其加入PATH变量中。\n* input: 定义在stage部分，会暂停 pipeline，提示你输入内容。\n* options: 用于配置 Jenkins pipeline 本身的选项，比如 options {retry (3) }指当pipeline失败时再重试2次。options指令 可定义在stage或pipeline部分。\n* parallel: 并行执行多个step。在pipeline插件 1.2版本后，parallel开始支 持对多个阶段进行并行执行。\n* parameters: 与input不同，parameters是 执行pipeline前传入的一些参数。\n* triggers: 用于定义执行pipeline的触发器。\n* when: 当满足when定义的条件时，阶段才执行。\n\n> 在使用指令时，需要注意的是每个指令都有自己的\"作用域\"。如果指令使用的位置不正确，Jenkins将会报错。\n\noptions 指令用于配置整个 Jenkins pipeline 本身的选项\n\n```groovy\npipeline {\n    agent any\n    options {\n        timeout(time: 1, unit: 'HOURS') \n        disableConcurrentBuilds()\n    }\n    stages {\n        stage('Example') {\n            steps {\n                echo 'Hello World'\n            }\n        }\n    }\n}\n```\n\n* 整个pipeline执行超过一个小时将中止\n* 禁止pipeline同时执行，避免抢占资源或调用冲突\n\nstage 的 options 指令类似于流水线根目录上的 options\n\n```groovy\npipeline {\n    agent any\n    stages {\n        stage('Example') {\n            options {\n                timeout(time: 1, unit: 'HOURS') \n            }\n            steps {\n                echo 'Hello World'\n            }\n        }\n    }\n}\n```\n* 指定 Example 阶段的执行超时时间, 在此之后，Jenkins 将中止流水线运行\n\n### 拓展\n> 在实际使用中，我们很多项目都需要单元测试以及导出报告的 stage，这时这两个stage 我们应该能够服用量，否则的话每个 Job 的 pipeline 都需要写一遍。有几种方式可以实现复用\n\n* 将公共的 pipeline 步骤导入到 Global Pipeline LIbraries，这个不是我们要讲的，感兴趣的话可以去官网看看： **[Jenkins 共享库](https:\u002F\u002Fwww.jenkins.io\u002Fzh\u002Fdoc\u002Fbook\u002Fpipeline\u002Fshared-libraries\u002F)** \n\n\n* 由于 pipeline 是用 groovy 脚本编写的，那么我们可以将公共的步骤抽出来，形成一个公共代码库，当需要引用公共库中的 stage 时，只需要将对应的 groovy 脚本 load 进来即可，这样做的好处是可以随时的修改，并且省去了上传到 **[Jenkins 共享库](https:\u002F\u002Fwww.jenkins.io\u002Fzh\u002Fdoc\u002Fbook\u002Fpipeline\u002Fshared-libraries\u002F)** 的步骤\n","Jenkins 是一款由 Java 编写的开源的``持续集成工具(ci\u002Fcd)","\u002FFpaDZS6eqq6kKuAuXti34InGnx1Y","2023-02-06T21:40:23.000Z",[6,12,42],[6],125,{"_id":41,"id":42,"created_at":43,"updated_at":44,"name":45,"description":45,"cover":9},[66,70,74],{"_id":67,"id":6,"created_at":68,"updated_at":68,"name":69},"6a294c7a9fbda20eb7c62de1","2022-12-08T14:04:04.000Z","工具方法",{"_id":71,"id":12,"created_at":72,"updated_at":72,"name":73},"6a294c7a9fbda20eb7c62de2","2022-12-08T14:04:09.000Z","工具收录",{"_id":75,"id":42,"created_at":76,"updated_at":76,"name":77},"6a294c7a9fbda20eb7c62de7","2022-12-08T14:05:07.000Z","学习记录",[79],{"name":80,"avatar":81,"email":82,"description":83,"role":84,"id":6},"Gavin","\u002Fblog\u002FWechatIMG133.jpeg","zzlwte@gmail.com","写代码的,也撸铁。白天搬 JavaScript 砖,晚上举铁,偶尔在这里写写技术沉淀和生活随想。",32,[86,91],{"id":87,"title":88,"cover":89,"created_date":90},14,"阿里云 docker image 加速","\u002Fblog\u002Fimg\u002F_MG_0605.JPG","2021-11-18T00:00:00.000Z",{"id":92,"title":93,"cover":94,"created_date":95},16,"flac 转 mp3","","2016-12-14T08:00:00.000Z",[]]