一、Free Style Job 和 Pipeline Job 的区别
Freestyle
Freestyle 学习成本底,容易掌握,方便配置,但是不利于项目以后的 维护
Pipeline
Pipline Job 有一定的学习成本,有利于项目以后都维护,比较匹配持续集成(CI)和持续部署、持续交付的原则(CD)。
Pipeline Job
基本语法
注释
Groovy的注释和java相同,如下是注释单行和多行的风格
/*
* 这是多行注释.
*/
// 这是单行注释
构建一个 Pipeline Job
#!groovy
pipeline {
// 指定运行构建的主机名和工作空间
agent {node {label '172.16.153.172'}}
environment {
// 定义全局环境变量
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"
}
parameters {
// 定义一个 选项参数
choice(
// 选项的两个值 dev 和 prod
choices: 'dev\nprod',
description: 'choose deploy environment',
name: 'deploy_env'
)
// 定义一个文本参数
string (name: 'version', defaultValue: '1.0', description: 'build version')
}
// 任务段,所有的任务都在这里声明
stages {
// 第一个任务段
stage("Checkout test repo") { // 给这个任务段起个名字
steps{ // 在这里声明具体要执行的任务步骤
// 利用 sh 模块 执行 shell 命令
sh 'git config --global http.sslVerify false'
dir ("${env.WORKSPACE}") { // 切换当前的工作目录到 jenkins 的工作目录
/* 用 git 模块切换分支 主 分支
* credentialsId 是访问 gitlab/github 的凭据唯一标识
*/
git branch: 'master',
credentialsId:"07b8e67f-31f6-4c48-ae0b-ab557cc0cea0 ",
url: '[email protected]:xiguatain/test_jenkis_freestyle.git'
}
}
}
// 第二个任务段
stage("Print env variable") {
steps {
dir ("${env.WORKSPACE}") {
sh """
echo "[INFO] Print env variable"
echo "Current deployment environment is $deploy_env" >> test.properties
echo "The build is $version" >> test.properties
echo "[INFO] Done..."
"""
}
}
}
// 第三个任务段
stage("Check test properties") {
steps{
dir ("${env.WORKSPACE}") {
sh """
echo "[INFO] Check test properties"
if [ -s test.properties ]
then
cat test.properties
echo "[INFO] Done..."
else
echo "test.properties is empty"
fi
"""
echo "[INFO] Build finished..."
}
}
}
}
}
pipeline 代码片段(参考示例)
总体代码框架
#!groovy
pipeline {
// 指定运行构建的主机名和工作空间
agent {node {label '172.16.153.172'}}
environment {
// 定义全局环境变量
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"
}
parameters {
// 定义各种参数
}
// 任务段,所有的任务都在这里声明
stages {
// 第一个任务段
stage("Checkout test repo") { // 给这个任务段起个名字
steps{ // 在这里声明具体要执行的任务步骤
// 利用 sh 模块 执行 shell 命令
sh 'git config --global http.sslVerify false'
dir ("${env.WORKSPACE}") { // 切换当前的工作目录到 jenkins 的工作目录
/* 用 git 模块切换分支 主 分支
* credentialsId 是访问 gitlab/github 的凭据唯一标识
*/
git branch: 'master',
credentialsId:"07b8e67f-31f6-4c48-ae0b-ab557cc0cea0 ",
url: '[email protected]:xiguatain/test_jenkis_freestyle.git'
}
}
}
// 第二个任务段
stage("Print env variable") {
steps {
dir ("${env.WORKSPACE}") {
sh """
echo "[INFO] Print env variable"
echo "Current deployment environment is $deploy_env" >> test.properties
echo "The build is $version" >> test.properties
echo "[INFO] Done..."
"""
}
}
}
// 第三个任务段
stage("Check test properties") {
steps{
dir ("${env.WORKSPACE}") {
sh """
echo "[INFO] Check test properties"
if [ -s test.properties ]
then
cat test.properties
echo "[INFO] Done..."
else
echo "test.properties is empty"
fi
"""
echo "[INFO] Build finished..."
}
}
}
}
}
agent
environment
parameters
parameters {
// 选项参数
choice(
// 选项的两个值 dev 和 prod
choices: 'dev\nprod',
description: 'choose deploy environment',
name: 'deploy_env'
)
// 文本参数
string (name: 'version', defaultValue: '1.0', description: 'build version')
// 文件参数
file (description: '''上传的文件会被保存在 Jenkins 的工作空间:
宿主机的 /apps/middle/jenkins/jenkins_home/workspace/ 目录下,保存名称均是 apps.zip
只能传文件,必须是 zip 包,否则无法解压文件。''', name: 'apps.zip')
}
如何使用ssh 执行远程命令,删除远程文件,传输本地文件到远程服务端
插件名称 SSH Pipeline Steps
官方网站: https://github.com/jenkinsci/ssh-steps-plugin
执行命令
node {
def remote = [:]
remote.name = 'test'
remote.host = 'test.domain.com'
remote.user = 'root'
remote.password = 'password'
remote.allowAnyHosts = true
stage('Remote SSH') {
sshCommand remote: remote, command: "ls -lrt"
sshCommand remote: remote, command: "for i in {1..5}; do echo -n \"Loop \$i \"; date ; sleep 1; done"
}
}
sshScript
此步骤在远程节点上执行给定的脚本(文件)并使用输出进行响应。
输入
钥匙 类型 描述
远程
远程、强制、有关更多详细信息,请参阅远程配置。
用于运行命令的主机配置。
脚本
字符串,必填
工作区中的脚本文件名,当前不支持带参数的脚本。对于该选项,您需要将文件复制到远程节点并将其作为命令运行。
失败无误
布尔值,默认值:。true
如果是 ,则不会发生作业失败,尽管在运行命令时出现错误。false
干运行
布尔值,默认值:false
如果为真,则不执行任何实际连接或操作。
例
node {
def remote = [:]
remote.name = 'test'
remote.host = 'test.domain.com'
remote.user = 'root'
remote.password = 'password'
remote.allowAnyHosts = true
stage('Remote SSH') {
writeFile file: 'abc.sh', text: 'ls -lrt'
sshScript remote: remote, script: "abc.sh"
}
}
sshPut
将文件或目录放入远程主机。
输入
钥匙 类型 描述
远程
远程、强制、有关更多详细信息,请参阅远程配置。
用于运行命令的主机配置。
从
字符串,必填
工作区中的文件或目录路径。
到
字符串,必填
远程节点上的文件或目录路径。
过滤器通过
字符串,可选,默认值为 。name
通过文件过滤器放置文件。可能的值是 java File 对象上的参数。
过滤器雷格
字符串,可选。
通过文件正则表达式(Groovy语法)放置文件。示例:/.xml$/ - 放置所有 xml 文件。
失败无误
布尔值,默认值:。true
如果是 ,则不会发生作业失败,尽管在运行命令时出现错误。false
干运行
布尔值,默认值:false
如果为真,则不执行任何实际连接或操作。
例
node {
def remote = [:]
remote.name = 'test'
remote.host = 'test.domain.com'
remote.user = 'root'
remote.password = 'password'
remote.allowAnyHosts = true
stage('Remote SSH') {
writeFile file: 'abc.sh', text: 'ls -lrt'
sshPut remote: remote, from: 'abc.sh', into: '.'
}
}
sshGet
从远程主机获取文件或目录。
输入
钥匙 类型 描述
远程
远程、强制、有关更多详细信息,请参阅远程配置。
用于运行命令的主机配置。
从
字符串,必填
来自远程节点的文件或目录路径。
到
字符串,必填
当前工作区上的文件或目录路径。
过滤器通过
字符串,可选,默认值为 。name
通过文件筛选器获取文件。可能的值是 java File 对象上的参数。
过滤器雷格
字符串,可选。
通过文件正则表达式(Groovy 语法)获取文件。示例:/.xml$/ - 获取所有 xml 文件。
失败无误
布尔值,默认值:。true
如果是 ,则不会发生作业失败,尽管在运行命令时出现错误。false
干运行
布尔值,默认值:false
如果为真,则不执行任何实际连接或操作。
例
node {
def remote = [:]
remote.name = 'test'
remote.host = 'test.domain.com'
remote.user = 'root'
remote.password = 'password'
remote.allowAnyHosts = true
stage('Remote SSH') {
sshGet remote: remote, from: 'abc.sh', into: 'abc_get.sh', override: true
}
}
ssh删除
删除远程主机上的文件或目录。
输入
钥匙 类型 描述
远程
远程、强制、有关更多详细信息,请参阅远程配置。
用于运行命令的主机配置。
路径
字符串,必填
远程节点上的文件或目录路径
失败无误
布尔值,默认值:。true
如果是 ,则不会发生作业失败,尽管在运行命令时出现错误。false
干运行
布尔值,默认值:false
如果为真,则不执行任何实际连接或操作。
例
node {
def remote = [:]
remote.name = 'test'
remote.host = 'test.domain.com'
remote.user = 'root'
remote.password = 'password'
remote.allowAnyHosts = true
stage('Remote SSH') {
sshRemove remote: remote, path: "abc.sh"
}
}
例子
与凭据
示例:这些步骤如何利用从 Jenkins 凭据存储中读取私钥。withCredentials
def remote = [:]
remote.name = "node-1"
remote.host = "10.000.000.153"
remote.allowAnyHosts = true
node {
withCredentials([sshUserPrivateKey(credentialsId: 'sshUser', keyFileVariable: 'identity', passphraseVariable: '', usernameVariable: 'userName')]) {
remote.user = userName
remote.identityFile = identity
stage("SSH Steps Rocks!") {
writeFile file: 'abc.sh', text: 'ls'
sshCommand remote: remote, command: 'for i in {1..5}; do echo -n \"Loop \$i \"; date ; sleep 1; done'
sshPut remote: remote, from: 'abc.sh', into: '.'
sshGet remote: remote, from: 'abc.sh', into: 'bac.sh', override: true
sshScript remote: remote, script: 'abc.sh'
sshRemove remote: remote, path: 'abc.sh'
}
}
}
###实例
def remote_host = ['x.x.x.x','x.x.x.x']
pipeline {
// 指定运行构建的主机名和工作空间
agent {
node { label 'master' }
}
options {
timestamps() //日志会有时间, 它对应了一个同名的插件
skipDefaultCheckout() //删除隐式checkout scm语句
//disableConcurrentBuilds() //禁止并行
timeout(time: 1, unit: 'HOURS') //流水线超时设置1h
buildDiscarder(logRotator(numToKeepStr: '3')) //设置构建历史保存个数
}
environment {
// 定义全局环境变量
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"
webUrl = 'https://x.x.x.x/spms/spms/Branch/SPMS_V200R002C01CUBE_HuaweiIot/SPMS-WEB'
auth_remote_166 = credentials('remote-host-166')
auth_nginx = credentials('nginx')
nginx_base_dir = "/apps"
remote_166_base_dir = "/apps/HCS/jenkins/html"
}
// 任务段,所有的任务都在这里声明
stages {
// 传输文件并部署
stage('Parallel Stage') {
// 任何一个阶段报错就立刻终止所有的阶段
failFast true
parallel {
stage('传输到 166 服务器') {
steps {
script {
def remote = [:]
remote.name = 'remote-host-166'
remote.host = 'x.x.x.x'
remote.user = env.AUTH_REMOTE_166_USR
remote.password = env.AUTH_REMOTE_166_PSW
remote.allowAnyHosts = true
//sh 'mkdir datav{1,2}'
writeFile file: 'datav1/a.sh', text: 'pwd'
writeFile file: 'datav2/b.sh', text: 'pwd2'
sshRemove remote: remote, path: "${env.remote_166_base_dir}/datav1 ${env.remote_166_base_dir}/datav2"
sshPut remote: remote, from: "${env.WORKSPACE}/datav1", into: "${env.remote_166_base_dir}"
sshPut remote: remote, from: "${env.WORKSPACE}/datav2", into: "${env.remote_166_base_dir}"
sshCommand remote: remote, command: "ls -lrt ${env.remote_166_base_dir}"
}
}
}
}
}
}
}