案例一:
这个脚本包括从Git仓库拉取代码、进行Maven构建,并将构建好的jar包复制到指定服务器。
pipeline {
agent any
stages {
stage('Prepare') {
steps {
script {
// 判断是否存在目录,没有则克隆,有则拉取
if (!fileExists('supervise-cloud')) {
echo "Cloning repository"
sh 'git clone ssh://git@192.168.0.99:9981/zhjg/zhengke/supervise-cloud.git'
} else {
echo "Pulling latest changes"
sh '''
cd supervise-cloud
git pull
'''
}
}
}
}
stage('Build') {
steps {
echo "Maven build start"
sh '''
export MAVEN_HOME=/root/apache-maven-3.9.2
export JAVA_HOME=/usr/local/java/jdk-1.8.0
export PATH=$MAVEN_HOME/bin:$JAVA_HOME/bin:$PATH
cd supervise-cloud
mvn clean compile package -Dmaven.test.skip=true
'''
}
}
stage('Deploy') {
steps {
echo "Deploying artifacts"
sh '''
scp supervise-cloud/supervise-auth/target/supervise-auth.jar root@192.168.0.106:/root
scp supervise-cloud/supervise-other-module/target/*.jar root@192.168.0.106:/root
'''
}
}
}
}
详细说明:
- Prepare 阶段:这个阶段会检查本地是否已经存在项目目录。如果不存在,则执行
git clone
克隆仓库;如果存在,则执行git pull
拉取最新代码。 - Build 阶段:设置环境变量并进入项目目录,使用 Maven 进行构建。这里跳过了测试并且指定了项目和pom文件位置。
- Deploy 阶段:使用
scp
命令将构建好的jar
包复制到远程服务器上。这里需要确保 Jenkins 服务器有权限访问目标服务器,并且ssh密钥已正确设置。
案例二:
需要在Jenkins流水线中停止supervise-gateway.jar应用,可以通过设置一个专门的停止阶段来实现。这个阶段将会使用kill
命令或其他方式来停止正在运行的Java进程。
Jenkinsfile 示例
假设应用是通过一个Java命令启动的,并且知道这个应用相关的一些信息(如使用的jar文件名),你可以在Jenkins流水线中这样写:
pipeline {
agent any
stages {
stage('Stop Application') {
steps {
script {
// 查找正在运行的Java应用的PID
sh '''
PID=$(ps aux | grep '[s]upervise-gateway.jar' | awk '{print $2}')
if [ -z "$PID" ]; then
echo "No application running."
else
echo "Stopping application with PID: $PID"
kill $PID
# 确认进程是否已经停止
while kill -0 $PID 2> /dev/null; do
echo "Waiting for application to stop..."
sleep 1
done
echo "Application stopped."
fi
'''
}
}
}
}
}
这个流水线脚本做了以下几件事:
-
查找Java进程:使用
ps
和grep
命令查找包含supervise-gateway.jar
的Java进程。这里使用[s]upervise-gateway.jar
的搜索模式是为了避免匹配grep
命令自己的进程。 -
停止进程:使用
kill
命令发送终止信号到找到的进程ID。如果找到多个进程,这个脚本将会停止第一个找到的进程。 -
确认停止:脚本会检查进程是否停止,如果没有停止,它会每秒检查一次直到进程停止。
案例三:
要将 Jenkins 的工作目录名称设置为一个变量,你可以在 Jenkinsfile 的开始部分定义一个环境变量,并在整个流程中使用这个变量。这样,你可以在不同的情况下更容易地修改工作目录的名称。下面是如何修改你的 Jenkinsfile 来实现这一点:
pipeline {
agent any
environment {
WORKSPACE_DIR = 'test' // 可以根据需要更改这个变量的值
}
stages {
stage('Prepare') {
steps {
script {
// 检查目录是否存在,如果不存在则克隆,如果存在则从dev分支拉取最新代码
if (!fileExists('supervise-cloud')) {
echo "Cloning repository"
sh 'git clone -b dev ssh://git@192.168.0.99:9981/zhjg/zhengke/supervise-cloud.git'
} else {
echo "Pulling latest changes"
sh '''
cd supervise-cloud
git checkout dev
git pull
'''
}
}
}
}
stage('Build') {
steps {
echo "Maven build start"
sh '''
export MAVEN_HOME=/root/apache-maven-3.9.2
export JAVA_HOME=/usr/local/java/jdk-1.8.0
export PATH=$MAVEN_HOME/bin:$JAVA_HOME/bin:$PATH
cd supervise-cloud
mvn clean compile package -Dmaven.test.skip=true
'''
}
}
stage('Deploy') {
steps {
script {
// 使用ssh连接到远程服务器,进行部署操作
sh '''
ssh -o StrictHostKeyChecking=no zhjgapp@192.168.0.108 << remotessh
if pgrep -f supervise-auth.jar; then
pkill -f supervise-auth.jar
echo "Application stopped"
else
echo "No running application found"
fi
if [ -f /home/zhjgapp/supervise-cloud/auth/supervise-auth.jar ]; then
mv /home/zhjgapp/supervise-cloud/auth/supervise-auth.jar /home/zhjgapp/supervise-cloud/back/supervise-auth-`date +%Y%m%d`.jar
echo "Old application backed up as supervise-auth-`date +%Y%m%d`.jar"
fi
exit
remotessh
'''
// 将新的jar文件scp到目标服务器
sh '''
scp -o StrictHostKeyChecking=no ${WORKSPACE_DIR}/supervise-cloud/supervise-auth/target/supervise-auth.jar zhjgapp@192.168.0.108:/home/zhjgapp/supervise-cloud/auth/
'''
// 重新登录到远程服务器启动新的应用
sh '''
ssh -o StrictHostKeyChecking=no zhjgapp@192.168.0.108 << remotessh
cd /home/zhjgapp/supervise-cloud/auth/
nohup java -Dfile.encoding=utf-8 -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -jar supervise-auth.jar > /dev/null 2>&1 &
echo "Application started"
exit
remotessh
'''
}
}
}
}
post {
always {
echo "Pipeline execution complete"
}
}
}
这里,WORKSPACE_DIR
变量定义在 environment
块内,并在 scp 命令中使用 ${WORKSPACE_DIR}
来代替原先直接使用的目录名。你可以根据需要轻松更改 WORKSPACE_DIR
的值,以适应不同的部署或环境需求。
案例三完整版
pipeline {
agent any
environment {
WORKSPACE_DIR = 'test-zhjg-supervise-gateway' //jenkins工作目录名称
}
stages {
stage('Prepare') {
steps {
script {
// 检查目录是否存在,如果不存在则克隆,如果存在则从dev分支拉取最新代码
if (!fileExists('supervise-cloud')) {
echo "Cloning repository"
sh 'git clone -b dev ssh://git@192.168.0.99:9981/zhjg/zhengke/supervise-cloud.git'
} else {
echo "Pulling latest changes"
sh '''
cd supervise-cloud
git checkout dev
git pull
'''
}
}
}
}
stage('Build') {
steps {
echo "Maven build start"
sh '''
export MAVEN_HOME=/root/apache-maven-3.9.2
export JAVA_HOME=/usr/local/java/jdk-1.8.0
export PATH=$MAVEN_HOME/bin:$JAVA_HOME/bin:$PATH
cd supervise-cloud
mvn clean compile package -Dmaven.test.skip=true
'''
}
}
stage('Deploy') {
steps {
script {
// 使用ssh连接到远程服务器,停止现有服务&备份jar包
sh '''
ssh -o StrictHostKeyChecking=no zhjgapp@192.168.0.108 << remotessh
if pgrep -f supervise-gateway.jar; then
pkill -f supervise-gateway.jar
echo "Application stopped"
else
echo "No running application found"
fi
if [ -f /home/zhjgapp/supervise-cloud/gateway/supervise-gateway.jar ]; then
mv /home/zhjgapp/supervise-cloud/gateway/supervise-gateway.jar /home/zhjgapp/supervise-cloud/back/supervise-gateway-`date +%Y%m%d-%H%M%S`.jar
echo "Old application backed up as supervise-gateway-`date +%Y%m%d-%H%M%S`.jar"
fi
# 删除超过30天的备份文件
find /home/zhjgapp/supervise-cloud/back/ -mtime +30 -type f -name '*.jar' -exec rm {} \\;
echo "Removed backups older than 30 days"
exit
remotessh
'''
// 将新的jar文件scp到目标服务器
sh '''
scp -o StrictHostKeyChecking=no /root/.jenkins/workspace/${WORKSPACE_DIR}/supervise-cloud/supervise-gateway/target/supervise-gateway.jar zhjgapp@192.168.0.108:/home/zhjgapp/supervise-cloud/gateway/
'''
// 重新登录到远程服务器启动新的应用
sh '''
ssh -o StrictHostKeyChecking=no zhjgapp@192.168.0.108 << remotessh
cd /home/zhjgapp/supervise-cloud/gateway/
nohup java -Dspring.profiles.active=test -Dfile.encoding=utf-8 -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -jar supervise-gateway.jar > /dev/null 2>&1 &
echo "Application started"
exit
remotessh
'''
}
}
}
}
post {
always {
echo "Pipeline execution complete"
}
}
}
这段代码是一个 Jenkins Pipeline 脚本,它定义了一个自动化流程,主要用于从源代码管理(如 Git)获取代码,构建项目,部署到服务器,并执行相关的清理工作。这种流程通常用于持续集成和持续部署(CI/CD)。下面是对各个部分的简单解释:
Pipeline 结构
-
agent any: 这指示 Jenkins 可以在任何可用的节点上运行这个 pipeline。
-
environment: 定义环境变量,这里定义的是
WORKSPACE_DIR
,即 Jenkins 工作目录名称。
Stages 解释
Prepare 阶段
- 检查目录: 判断
supervise-cloud
目录是否存在。- 如果不存在,执行
git clone
命令从远程 Git 仓库克隆代码。 - 如果存在,切换到
dev
分支并拉取最新代码,以保持代码更新。
- 如果不存在,执行
Build 阶段
- 构建: 使用 Maven 来构建项目,这包括编译代码和打包。
- 设置 Maven 和 Java 的环境变量。
- 执行
mvn clean compile package
命令来清理、编译和打包应用,同时跳过单元测试。
Deploy 阶段
- 部署:
- 停止服务: 使用
ssh
连接到远程服务器,检查并停止正在运行的supervise-gateway.jar
应用。 - 备份旧应用: 如果找到旧的 jar 文件,将其移动到备份目录,并以当前日期和时间为后缀重命名。
- 清理旧备份: 删除30天前的备份文件以节省空间。
- 部署新应用: 将新构建的 jar 文件通过
scp
命令复制到远程服务器。 - 启动新服务: 在远程服务器上启动新的 jar 文件。
- 停止服务: 使用
Post Actions
- always: 无论 pipeline 执行成功或失败,都会执行的步骤,这里是打印“Pipeline execution complete”。
总结
这个 Jenkins Pipeline 脚本为开发提供了一个自动化的构建、部署流程,帮助团队实现快速迭代和部署,确保代码的快速交付和部署到生产环境中。通过自动化这些步骤,可以减少人为错误,提高效率和可靠性。
案例四
pipeline {
agent any
environment {
work_space = "${env.WORKSPACE}"
work_base = 'fangzhi805-parent'
git_url = 'http://jenkins:Jxxxxft@git.xxxxxx.com:180/fangzhi805/fangzhi805-parent.git'
git_branch = 'dev'
target_env = 'dev'
gitfile = "${work_space}/${work_base}/.git/config"
package_path = 'ucenter-parent/ucenter-biz'
server_ip_list = "10.217.88.212"
deploy_server_user = 'fangzhi'
deploy_server_bin_dir = '/home/fangzhi/ucenter/bin'
deploy_server_bin_back_dir = '/home/fangzhi/ucenter/binback'
deploy_server_sh_dir = '/home/fangzhi/ucenter/shbin'
deploy_stop_sh='ucenterbiz_stop.sh'
deploy_start_sh='ucenterbiz_start.sh'
}
stages {
stage('git clone/pull') {
steps {
echo "git clone/pull start"
/*第一次用git clone*/
echo "gitfile: ${gitfile}"
script {
if (fileExists(gitfile) == false) {
sh 'git clone -b ${git_branch} ${git_url}'
}
}
/*第二次以及以后用git pull*/
sh '''
cd ${work_base}
git pull
'''
echo "git clone/pull end"
}
}
stage('build') {
steps {
echo "maven build start"
sh '''
export MAVEN_HOME=/root/apache-maven-3.9.6
export JAVA_HOME=/root/jdk-21.0.2
export PATH=$MAVEN_HOME/bin:$JAVA_HOME/bin:$PATH
cd ${work_base}
mvn clean compile package -Dmaven.test.skip=true -pl ${package_path} -am -f pom.xml
'''
echo "maven build end"
}
}
stage('deploy') {
steps {
script {
if (server_ip_list.length() == 0) {
println("没有可用于执行的服务器")
} else {
for ( deploy_server_ip in server_ip_list.tokenize(",")) {
echo "deploy_server ${deploy_server_ip}"
echo "remote 1 start"
sh """
#登陆服务器
ssh -o StrictHostKeyChecking=no ${deploy_server_user}@${deploy_server_ip} << remotessh
#停止服务
cd ${deploy_server_sh_dir}
sh ${deploy_stop_sh}
#可执行文件备份
mkdir -p ${deploy_server_bin_back_dir}
mkdir -p ${deploy_server_bin_dir}
tar -czvf ${deploy_server_bin_back_dir}/bin.`date +%Y%m%d%H%M%S`.tgz ${deploy_server_bin_dir}
rm -rf ${deploy_server_bin_dir}/*
exit
remotessh
"""
echo "remote 1 end"
echo "remote 2 start"
echo "scp -o StrictHostKeyChecking=no -r ${work_space}/${work_base}/${package_path}/target/* ${deploy_server_user}@${deploy_server_ip}:${deploy_server_bin_dir}/ "
sh """
#应用部署
scp -o StrictHostKeyChecking=no -r ${work_space}/${work_base}/${package_path}/target/* ${deploy_server_user}@${deploy_server_ip}:${deploy_server_bin_dir}/
"""
echo "remote 2 end"
echo "remote 3 start"
sh """
#启动服务
ssh -o StrictHostKeyChecking=no ${deploy_server_user}@${deploy_server_ip} << remotessh
cd ${deploy_server_sh_dir}
sh ${deploy_start_sh}
exit
remotessh
"""
echo "remote 3 end"
}
}
}
}
}
}
}
这段代码是 Jenkins 的声明式 pipeline 脚本,用于自动化地执行软件的版本控制拉取、构建、和部署过程。这里面详细定义了各个阶段的操作,我将逐一解释每个阶段的作用和操作:
环境变量设定 (environment
)
- 定义了一系列的环境变量,这些变量被用于后续的各个阶段,包括工作目录、Git 仓库地址、分支名、部署脚本的位置等。
Git 克隆/拉取 (git clone/pull
)
- 检查
.git/config
文件是否存在来决定是进行git clone
还是git pull
。如果是第一次,则通过git clone
命令从指定的仓库和分支拉取代码;如果不是第一次,则直接在已有的目录中执行git pull
来更新代码。
构建 (build
)
- 使用 Maven 进行构建。首先设置 Maven 和 Java 的环境变量,然后在指定的模块目录中执行 Maven 命令进行编译和打包,跳过单元测试。
部署 (deploy
)
- 检查服务器 IP 列表,如果非空,则对每个服务器进行以下操作:
- 停止服务:登录到服务器,执行停止服务的脚本。
- 备份当前部署:在服务器上创建备份目录,备份当前的可执行文件,并清空部署目录。
- 部署新应用:通过
scp
命令将新构建的应用文件从 Jenkins 服务器传输到目标服务器的部署目录。 - 启动服务:在服务器上执行启动服务的脚本。
Jenkins Pipeline 的流程控制
- 这个 pipeline 具备了自动化部署的完整流程:从源码的版本控制开始,到应用的构建、部署,再到最后的启动服务,整个流程都是自动化的。这样可以极大地提升软件开发和部署的效率,减少人为错误,确保部署的一致性和可重复性。
安全性和健壮性注意事项
- 使用了 SSH 的
StrictHostKeyChecking=no
选项来避免人工干预。在生产环境中,建议更安全地处理 SSH 密钥和主机密钥的确认过程,例如使用已知的主机密钥文件。 - 通过在 SSH 和 SCP 命令中指定用户和服务器 IP 进行操作,需要确保 Jenkins 服务器具有相应服务器的适当访问权限,并且部署账户的安全性得到妥善管理。
- 备份和清理操作有助于防止新部署影响现有环境,并提供回滚的可能性,增加系统的稳定性和可恢复性。
案例五
pipeline {
agent any
environment {
// 定义环境变量以便在脚本中复用
job_name = "${JOB_NAME}" // 作业名称
repo_url = "http://jenkins:JieYiS%40ft@192.168.1.182:11180/kushan/firefightingproject/kunshan-fire-web.git" // Git 仓库 URL
branch = "dev" // 分支名称
node_path = "/root/node-v18.20.1-linux-x64/bin" // 容器中Node.js 路径
npm_registry = "http://192.168.1.111:31111/repository/npm-group/" // npm 注册表地址
remote_user = "firemanager" // 远程服务器用户名
remote_host = "192.168.1.223" // 远程服务器地址
remote_path = "/home/firemanager/web" // 远程服务器路径
local_workspace = "/root/.jenkins/workspace/dev-kunshan-fire-web/kunshan-fire-web" // 本地工作空间路径
}
stages {
stage('git clone/pull') {
steps {
script {
// 检查存储库目录是否存在
if (!fileExists('kunshan-fire-web')) {
echo "git clone start"
// 如果目录不存在,则克隆存储库
sh "git clone -b ${branch} ${repo_url}"
} else {
echo "git pull start"
// 如果目录存在,则拉取最新更改
sh '''
cd kunshan-fire-web
git pull
'''
}
}
}
}
stage('install and build') {
steps {
script {
// 检查 node_modules 目录是否存在,以确定是否需要安装依赖项
if (!fileExists("${local_workspace}/node_modules")) {
echo "npm install start"
// 设置 npm 注册表并安装依赖项(如果 node_modules 不存在)
sh '''
export PATH=${node_path}:$PATH
npm config set registry ${npm_registry}
cd kunshan-fire-web
yarn
'''
}
// 始终构建项目
echo "yarn build start"
sh '''
export PATH=${node_path}:$PATH
cd kunshan-fire-web
yarn build:prod
'''
}
}
}
stage('deploy') {
steps {
script {
// 连接到远程服务器并删除现有的 dist 目录
echo "remote 1 start"
sh '''
ssh -o StrictHostKeyChecking=no ${remote_user}@${remote_host} << remotessh
cd ${remote_path}
rm -rf dist
exit
remotessh
'''
echo "remote 1 end"
// 将新的 dist 目录复制到远程服务器
echo "remote 2 start"
sh '''
scp -o StrictHostKeyChecking=no -r ${local_workspace}/dist ${remote_user}@${remote_host}:${remote_path}/
'''
echo "remote 2 end"
}
}
}
}
}
前端发布流水线
案例四
pipeline {
agent any
stages {
stage('Git 克隆/拉取') {
steps {
echo "Git 克隆/拉取 开始"
script {
// 如果项目目录不存在,则进行克隆
if (!fileExists("supervise-web")) {
echo "克隆仓库"
sh 'git clone -b dev ssh://git@192.168.0.99/zhjg/zhengke/supervise-web.git'
} else {
// 如果项目目录存在,则进行拉取
echo "拉取最新代码"
dir('supervise-web') {
sh 'git pull origin dev'
}
}
}
echo "Git 克隆/拉取 结束"
}
}
stage('安装依赖和构建') {
steps {
echo "npm 安装 开始"
script {
sh '''
# 设置 Node.js 环境路径
export PATH=/root/node-v16.20.2-linux-x64/bin:$PATH
# 设置 npm 仓库地址
npm config set registry http://repo.jieyisoft.com:31111/repository/npm-group/
cd supervise-web
# 检查 node_modules 目录是否存在
if [ ! -d "node_modules" ]; then
echo "安装依赖包"
yarn install
else
echo "依赖包已存在,跳过安装"
fi
# 构建项目
yarn build:stage118
'''
}
echo "npm 安装 结束"
}
}
stage('部署') {
steps {
echo "远程备份和部署 开始"
// 在远程服务器上备份旧文件并删除
sh '''
ssh -o StrictHostKeyChecking=no root@192.168.0.106 << 'EOF'
cd /home/project/supervise-ui/test
tar -czvf ../bak/test_bak_$(date +%Y%m%d).tar.gz ./*
rm -rf /home/project/supervise-ui/test/*
exit
EOF
'''
// 将新文件复制到远程服务器
sh '''
scp -o StrictHostKeyChecking=no -r /root/.jenkins/workspace/test-zhjg-supervise-web/supervise-web/dist/test/* root@192.168.0.106:/home/project/supervise-ui/test/
'''
echo "远程备份和部署 结束"
}
}
}
}