Jenkins持续部署-创建差量更新包
Jenkins持续部署-创建差量更新包
目录
Jenkins持续集成学习-Windows环境进行.Net开发1
Jenkins持续集成学习-Windows环境进行.Net开发2
Jenkins持续集成学习-Windows环境进行.Net开发3
Jenkins持续集成学习-Windows环境进行.Net开发4
Jenkins持续集成学习-搭建jenkins问题汇总
Jenkins持续部署-Windows环境持续部署探究1
Jenkins持续部署-自动生成版本号
Jenkins持续部署-创建差量更新包
前言
上一篇文章介绍关于版本号的自动生成逻辑,本篇文章主要介绍通过脚本跟版本号创建程序的差量包。
目的
本章主要是通过jenkins持续集成之后通过powershell生成差量更新包与全量更新包,然后将他们上传到FTP上。
详细流程
当jenkins编译完成之后,我们需要处理以下事项。
打包全量更新包
打包全量更新包-.-> 创建差量更新包
创建差量更新包
创建差量更新包 -.-> 远程创建FTP文件目录结构
远程创建FTP文件目录结构 -.-> 将打包文件上传到服务器
``` -->
- jenkins编译成功,先获取所有exe,dll,获取他们的版本号,创建文件更新清单。
- 将所有的exe,dll,pdb以及文件更新清单进行压缩打包,压缩文件名为指定主程序的版本号。
- 将上个版本的文件压缩包解压,若没有上个版本的文件压缩包,则无需上传差量更新包。
- 比较当前文件更新清单和上个版本的文件更新清单。若文件名一样,版本号也一样,则删除编译出的对应文件。
- 获取剩下的所有exe,dll,pdb以及文件更新清单进行压缩打包,压缩文件名为指定主程序的版本号_Diff。
- 遍历每个服务配置。
- 获取上传的相对目录为Job名/版本号.zip,调用远程命令,检查服务器是否存在目录,没有的话则创建目录。
- 目录创建完毕后,将压缩文件上传,若有差量更新包则也需要上传。
- 最后调用远程命令对服务进行卸载与更新。
生成版本号
上一章介绍了.net
环境下如何自动生成版本号的逻辑,这里不再介绍。有兴趣的可以看《Jenkins持续部署-自动生成版本号
》
获取版本号
$version =(Get-ChildItem $executeFile).VersionInfo.FileVersion
$executeFile
为可执行的exe文件。通过Get-ChildItem 获取到该文件。- 通过
VersionInfo.FileVersion
或VersionInfo.ProductVersion
获取到文件的文件版本号。
不知道为什么和文件右键属性看到的两个版本号有点区别右击属性的文件版本号和产品版本可能不一样,但是通过代码获取到的都是一样的
创建文件更新清单
为了能够生成程序差量更新包,减少程序更新时的更新包大小,需要可以通过比较当前版本和上一个版本的各个文件的版本号信息。通过将该文件保存成一份文件清单。再比较时直接通过该文件清单进行比对,能够很方便的生成从差量的文件清单。同时文件清单能够清晰的列出每个需要更新的文件和文件版本号,给人看会比较直观。
主要是我们自己需要用该文件,也可以不用该文件,直接获取所有文件,对比他们的文件名和版本号是否一致也可以。
$programFiles = Get-ChildItem *.dll,*.exe
$updateListFileName = "FileUpdateList.txt"
Create-FileUpdateList -files $programFiles -fileName $updateListFileName
function Create-FileUpdateList(){
param([System.IO.FileInfo[]]$files,[string]$fileName)
## 删除原始的清单文件
if(Test-Path $fileName)
{
Write-Host "Remove Old UpdateList File"
Remove-Item $fileName
}
$array=New-Object System.Collections.ArrayList
foreach($file in $files)
{
## 获取每个文件版本号
$fileVersion =(Get-ChildItem $file).VersionInfo.ProductVersion
$fileInfo="" | Select-Object -Property FileName,Version
$fileInfo.FileName = $file.Name
$fileInfo.Version = $fileVersion
## 追加到文件
$null = $array.Add($fileInfo)
Write-Host "Update File:"$file.Name ",Version:" $fileVersion
}
$json = ConvertTo-Json $array.ToArray()
$json >> $fileName
}
- 通过
Get-ChildItem *.dll,*.exe
获取当前目录所有的dll和exe文件 - 将更新清单文件名设置为
FileUpdateList.txt
,若已经存在更新清单文件,则删除旧的重新生成。 - 通过
New-Object
创建一个.Net的集合,用于存放每个文件的文件信息。 $fileInfo="" | Select-Object -Property FileName,Version
定义了一个自定义对象类型,包含了文件名和版本号2个属性。- 将每个文件的文件名和版本号保存到集合中
- 将集合转化为Json格式保存到文件中.
由于我需要在powershell2.0
的环境上执行脚本,powershell2.0
没有Json读写的api,这里使用的是别人写的一个脚本生成json格式的字符串。
function ConvertTo-Json
{
param(
$InputObject
)
if( $InputObject -is [string]){
"`"{0}`"" -f $InputObject
}
elseif( $InputObject -is [bool])
{
$InputObject.ToString().ToLower()
}
elseif( $null -eq $InputObject){
"null"
}
elseif( $InputObject -is [pscustomobject])
{
$result = "$space{`r`n"
$properties = $InputObject | Get-Member -MemberType NoteProperty |
ForEach-Object {
"`"{0}`": {1}" -f $_.Name, (ConvertTo-Json $InputObject.($_.Name))
}
$result += $properties -join ",`r`n"
$result += "$space`r`n}"
$result
}
elseif( $InputObject -is [hashtable])
{
$result = "{`r`n"
$properties = $InputObject.Keys |
ForEach-Object {
"`"{0}`": {1}" -f $_, (ConvertTo-Json $InputObject[$_])
}
$result += $properties -join ",`r`n"
$result += "`r`n}"
$result
}
elseif( $InputObject -is [array])
{
$result = "[`r`n"
$items = @()
for ($i=0;$i -lt $InputObject.length;$i++)
{
$items += ConvertTo-Json $InputObject[$i]
}
$result += $items -join ",`r`n"
$result += "`r`n]"
$result
}
else{
$InputObject.ToString()
}
}
压缩
将所有文件进行压缩,压缩文件名为版本号。
function New-ZipFile()
{
param(## The name of the zip archive to create
[object[]]$files,
$zipName = $(throw "Specify a zip file name"),
## Switch to delete the zip archive if it already exists.
[Switch] $Force)
## Check if the file exists already. If it does, check
## for -Force - generate an error if not specified.
if(Test-Path $zipName)
{
if($Force)
{
Write-Host "Remove File:" $zipName
Remove-Item $zipName
}
else
{
throw "Item with specified name $zipName already exists."
}
}
## Add the DLL that helps with file compression
Add-Type -Assembly System
try
{
#打开或创建文件流
$compressedFileStream = [System.IO.File]::Open($zipName,[System.IO.FileMode]::OpenOrCreate)
#创建压缩文件流
$compressionStream = New-Object ICSharpCode.SharpZipLib.Zip.ZipOutputStream($compressedFileStream)
## Go through each file in the input, adding it to the Zip file
## specified
foreach($file in $files)
{
## Skip the current file if it is the zip file itself
if($file.FullName -eq $zipName)
{
continue
}
## Skip directories
if($file.PSIsContainer)
{
continue
}
#读取每个文件进行压缩
try
{
#打开文件
$originalFileStream = [System.IO.File]::Open($file.FullName,[System.IO.FileMode]::Open)
$entry = New-Object ICSharpCode.SharpZipLib.Zip.ZipEntry($file.Name)
$compressionStream.PutNextEntry($entry);
$bytes = New-Object Byte[] $originalFileStream.Length
#读取文件流
$null = $originalFileStream.Read($bytes,0,$bytes.Length)
#写入到压缩流
$compressionStream.Write($bytes,0,$bytes.Length)
}
finally
{
$originalFileStream.Dispose()
}
}
}
catch{
$Error
Remove-Item $Path
}
finally
{
## Close the file
$compressionStream.Dispose()
$compressedFileStream.Dispose()
$compressionStream = $null
$compressedFileStream = $null
}
}
- 由于
powershell2.0
没有内部的压缩解压方法。这里使用.net的ICSharpCode.SharpZipLib.dll
进行压缩。 - 在
powershell
中可以通过New-Object Byte[]
创建.net的字节数组
,若构造函数需要传参则直接将参数写到后面即可。
该脚本不支持带文件夹的压缩。
获取上个版本的包
由于我定义的都是4位版本号,前三位是需求号,最后一位是修订号。因此我直接通过前三位获取上个版本的压缩包文件即可,若没有,则无需创建差量更新包。
function Get-LastPackage($currentVersion,$majorVersion)
{
#默认上个版本号就是当前版本号
$lastFileName = $null
$lastMajorVersion = $null
$lastVersion = $null
#读取上一个版本的压缩文件
# 获取所有文件夹,程序目录下的目录都是版本号目录
$allFile = Get-ChildItem | Where-Object{ $_.Name -match '(\d*\.\d*\.\d*.\d*)\.zip' }
if($null -eq $allFile)
{
Write-Host "No Last Package"
return
}
## 获取上一个版本号最新的修改
$allFile = $allFile | Where-Object {$_.Name -lt $majorVersion} | Sort-Object -descending
## 判断是否有比当前版本小的
if($null -eq $allFile)
{
## 没有历史的大版本号,则全量更新,和当前版本的主版本号一样
Write-Host "No Last Package"
return
}
#有多个文件如2.25.0,2.24.1,则获取到的是数组
elseif($allFile -is [array])
{
##存在历史更新,则获取上一个版本的更新目录
$lastFileName = $allFile[0]
}
#只有一个目录,首个版本打包时则获取到的是DirectoryInfo
else
{
$lastFileName = $allFile
}
## 获取最新的版本
$lastVersion =[System.IO.Path]::GetFileNameWithoutExtension($lastFileName)
$lastMajorVersion = [System.IO.Path]::GetFileNameWithoutExtension($lastVersion)
#返回文件名 主版本号 版本号
$lastFileName
$lastVersion
$lastMajorVersion
}
- 我通过正则筛选出文件格式为
四位数字版本.zip
的文件。 - 然后对筛选出的文件名进行排序。
- 最后获取比当前版本号小的上一个版本号。最后返回上个版本的完整文件路径及版本号信息。
创建差量更新包
我只需要根据两个文件清单进行文件名和版本号的对比,如果同一个文件的版本号一样,则该文件无需更新。
$lastUnpackDir = UnZip $lastZipFullName $lastVersion
$currentUpdateObject = Read-Json $currentUpdateListFile
$lastUpdateObject = Read-Json $lastUpdateListFile
$array = New-Object System.Collections.ArrayList
#比较两个清单文件
foreach($currentFile in $currentUpdateObject)
{
if($currentFile -eq "FileUpdateList.txt")
{
#跳过清单文件
continue
}
##遍历json数组数组对象本身也会遍历,且值为空
if($null -eq $currentFile.FileName)
{
#跳过清单文件
continue
}
#当前清单每个文件去上个版本查找
$lastFile = $lastUpdateObject | Where-Object {$_.FileName -eq $currentFile.FileName} | Select-Object -First 1
#找到文件,判断版本号
if($lastFile.Version -eq $currentFile.Version)
{
#版本号一样则不需要更新
$sameFile = Join-Path $currentUnpackDir $lastFile.FileName
$null = $array.Add($sameFile)
continue
}
}
- 先解压出上个版本的压缩文件。
- 然后读取两个版本的文件清单。
- 将一样的文件加入到一个列表中。
有了重复文件的列表,接下来就可以将重复文件都删除。最后剩下差量更新的文件
if($array.Count -eq $currentUpdateObject.Length - 1)
{
#所有都一样,不需要更新
Write-Host "No Modified File"
return $false
}
else
{
#存在不一样的包,则更新所有
foreach($sameFile in $array)
{
Write-Host "Remove Not Modified File " $sameFile
Remove-Item $sameFile
#同时删除pdb文件
$pdbFile = [System.IO.Path]::GetFileNameWithoutExtension($sameFile)+".pdb"
if(Test-Path $pdbFile)
{
Remove-Item $pdbFile
}
}
#重新获取解压的目录
$diffFiles = Get-ChildItem *.dll,*.exe
#创建新的清单文件
Create-FileUpdateList -files $diffFiles -fileName $currentUpdateListFile
#重新压缩所有文件
$files = Get-ChildItem *.dll,*.pdb,*.exe,"FileUpdateList.txt"
Write-Host "Need Update File " $files
$diffZipFullName = [System.IO.Path]::GetFileNameWithoutExtension($currentZipFullName)+"_diff.zip"
New-ZipFile -files $files -Path $diffZipFullName -Force true
}
#移除上个版本的解压出的压缩文件夹
Write-Host "Remove Last Update Package dir" $lastUnpackDir
Get-ChildItem $lastUnpackDir | Remove-Item -Recurse
Remove-Item $lastUnpackDir -Recurse
$return $true
- 比较数组的数量和当前读取到的文件数量是否一样,若一致表示所有文件都一样,则无需更新,返回
false
表示没有生成差量更新文件。就不用创建差量更新文件了。否则则删除所有的文件和对应的符号文件。 - 然后将所有的差量文件进行压缩,文件后面加上_diff表示是差量更新的文件。
- 最后把解压出来的上个版本的文件和文件加都删除掉。返回
true
表示生成了差量更新文件。
读取服务器Json配置
全量和差量文件生成完毕后就可以将文件上传到指定的服务器了。我将服务器的配置信息保存到了ServerInfo.Json
文件中,这样想添加其他服务器只要修改一下这个配置文件即可。读取配置的服务器,ServerInfo.Json
包含了服务器的一些信息,包括地址,用户名,及一些路径配置。
$config = Read-Json "ServerInfo.json"
foreach($itemConfig in $config)
{
Remote-CreateDic -userName $itemConfig.UserName -password $itemConfig.Password -address $itemConfig.Address -jobName $ftpFileName -programeDir $itemConfig.ProgramDir -ErrorAction Stop
#目标 ftp://host:port/xxx/xxx.zip
$destination = "ftp://"+$itemConfig.FTP.Host+":"+$itemConfig.FTP.Port+"/"+$ftpFileName
# FTP上传压缩包
FTP-UpdateFile -file $zipFullName -destination $destination -userName $itemConfig.FTP.UserName -password $itemConfig.FTP.Password -ErrorAction Stop
if($hasDiffFile ){
$ftpFileName = Join-Path $ENV:JOB_NAME ($version+"_diff.zip")
FTP-UpdateFile -file $zipFullName -destination $destination -userName $itemConfig.FTP.UserName -password $itemConfig.FTP.Password -ErrorAction Stop
}
}
- 通过
Remote-CreateDic
执行远程创建文件夹的命令。 - 通过
FTP-UpdateFile
将全量更新包和差量更新包都上传到指定的服务器上。
远程创建文件夹目录
在上传到FTP上时,若有必要则需要先在FTP上创建指定的文件夹,避免上传文件夹的时候由于没有文件夹导致上传失败。
由于需要远程调用,因此需要传递用户,密码和服务器地址。同时还要包含jenkins当前的job名称以及远程服务器程序上传路径。上传的路径约定为FTP地址/Job名称/版本号.zip
function Remote-CreateDic()
{
param([string] $userName=$(throw "Parameter missing: -userName"),
[string] $password=$(throw "Parameter missing: -password"),
[string] $address=$(throw "Parameter missing: -address"),
[string] $jobName=$(throw "Parameter missing: -jobName"),
[string] $programeDir=$(throw "Parameter missing: -programeDir"))
#非域用户需要添加\,否则远程调用有问题
if(!$userName.StartsWith('\'))
{
$userName="\"+$userName
}
$secpwd = convertto-securestring $password -asplaintext -force
$cred = new-object System.Management.Automation.PSCredential -argumentlist $userName,$secpwd
#程序存放目录和当前的jenkins job目录合并后是服务器锁在的FTP程序存放目录
$zipFile= [System.IO.Path]::Combine($programeDir,$jobName)
#备份程序
invoke-command -computername $address -Credential $cred -command {
param([string]$file)
#获取文件夹路径
$dir = [System.IO.Path]::GetDirectoryName($file)
if(Test-Path $dir){
Write-Host "Dic exists :" $dir
#文件夹存在
if(Test-Path $file)
{
#压缩文件已存在.不允许,版本号没变。必须改变
throw $file + "exists,retry after change version"
}
}
else
{
# 判断文件夹是否存在
# 没有文件夹则创建,否则首次FTP上传没有文件夹时则会上传失败
#防止输出
$null = New-Item -Path $dir -Type Directory
}
} -ArgumentList $zipFile -ErrorAction Stop
}
FTP上传
FTP上传可以调用.Net的WebClient上传文件的方法处理。
function FTP-UpdateFile()
{
param([String]$file=$(throw "Parameter missing: -name file"),
[String]$destination=$(throw "Parameter missing: -name destination"),
[String]$userName=$(throw "Parameter missing: -name userName"),
[String]$password=$(throw "Parameter missing: -name destination"))
$pwd=ConvertTo-SecureString $password -AsPlainText -Force; #111111为密码
$cred=New-Object System.Management.Automation.PSCredential($userName,$pwd); #创建自动认证对象
$wc = New-Object System.Net.WebClient
try
{
$wc.Credentials = $cred
Write-Host "upload to ftp. " $file "->" $destination
$wc.UploadFile($destination, $file)
Write-Host "upload success "
}
finally
{
$wc.Dispose()
Write-Host "close ftp. "
}
}
总结
本文对Windows下的持续部署包创建和上传的逻辑继续了说明,主要通过自动生成的版本号继续判断与比较哪些库包需要更新。最终将库包通过FTP上传到各个服务器上。最后就可以调用各个服务器的远程脚本进行服务的卸载与更新了。
- Windows PowerShell 入门
- Powershell变量的作用域
- Windows Remote Management
- windows服务器远程执行命令(PowerShell+WinRM)
- winServer-常用winrm命令
- Use Powershell to start a GUI program on a remote machine
微信扫一扫二维码关注订阅号杰哥技术分享
本文地址:https://www.cnblogs.com/Jack-Blog/p/11255314.html
作者博客:杰哥很忙
欢迎转载,请在明显位置给出出处及链接
Jenkins持续部署-创建差量更新包的更多相关文章
- Jenkins持续部署-自动生成版本号
目录 Jenkins持续部署-自动生成版本号 目录 前言 目的 详细流程 获取SVN Reversion 获取需求号 设置编译前读取版本号 总结 参考文献 Jenkins持续部署-自动生成版本号 目录 ...
- Jenkins持续部署-Windows环境持续部署探究1
目录 Jenkins持续部署-Windows环境持续部署探究1 目录 前言 目的 方案流程 技术实现 PowerShell FTP上传插件 环境变量插件 脚本执行 远程调用 升级服务 启动服务 总结 ...
- Jenkins持续部署
Jenkins持续部署 Jenkins提供很好的连续部署和交付的支持.看一下部署任何软件开发的流程,将如下图所示. 连续部署的主要部分,是确保其上面所示的整个过程是自动化的.Jenkins实现所有这些 ...
- Docker + Jenkins 持续部署 ASP.NET Core 项目
Docker 是个好东西,特别是用它来部署 ASP.NET Core Web 项目的时候,但是仅仅的让程序运行起来远远不能满足我的需求,如果能够像 DaoCloud 提供的持续集成服务那样,检测 gi ...
- JAVA项目如何通过Docker实现Jenkins持续部署
原文地址:http://blog.51cto.com/dadonggg/1957691 本篇实操性的案例讲解——JAVA项目如何通过Docker实现持续部署(只需简单四步), 即:开发通过git pu ...
- Mac上安装Jenkins持续部署初体验
1.首先去官网下载安装包 https://jenkins.io/doc/book/installing/ 安装完成后,很不幸,无法访问他的默认站点 查了一堆资料,有的说环境变量没有配置,有的说没有执行 ...
- gitlab+jenkins 持续部署自动化测试
背景:为了减少测试部署时间和减少不必要的重复工作,采用持续集成的方式进行部署,当gitlab的release (测试)分支有代码变动时,自动拉取代码部署测试环境,并进行接口回归测试 优点:部署自动化, ...
- [持续集成]Jenkins 自动化部署 Maven 工程
一.Jenkins 持续部署原理图 基础服务: 1 SVN 服务 SVN是Subversion的简称,是一个开放源代码的版本控制系统.说得简单一点SVN就是用于多个人共同开发同一个项目,共用资源的目的 ...
- Linux-GitLab+Jenkins持续集成+自动化部署
GitLab+Jenkins持续集成+自动化部署 什么是持续集成? (1)Continuous integration (CI) 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个 ...
随机推荐
- Spring Cloud全链路追踪实现(Sleuth+Zipkin+RabbitMQ+ES+Kibana)
简介 在微服务架构下存在多个服务之间的相互调用,当某个请求变慢或不可用时,我们如何快速定位服务故障点呢?链路追踪的实现就是为了解决这一问题,本文采用Sleuth+Zipkin+RabbitMQ+ES+ ...
- Centos7离线安装mysql8
linux版本:Centois7 mysql版本:5.7 一.安装 1.下载mysql离线安装包 下载地址:https://dev.mysql.com/downloads/mysql/ 选择如下: [ ...
- never下的easysql
什么是EasySql 在我们早期写的代码中,想实现组装灵活的sql语句与参数,我们可以去翻阅早期自己写的代码 var @sb = new StringBuilder(); sb.Append(&quo ...
- Mac sublime text3 安装插件
一.下载Mac版sublime text3 下载地址:http://www.pc6.com/mac/120663.html(参考) 2.安装后打开 1.在界面的最上端找到tools(英文版),选择第一 ...
- 【转】JDK 内存参数含义
Eclipse崩溃,错误提示: MyEclipse has detected that less than 5% of the 64MB of Perm Gen (Non-heap memory) ...
- CI框架使用(一)
CI框架的使用是很简单,也 是mvc模式.其中有好多类直接调用. 在使用帮助函数的时候,都需要手动加载,或者是在配置文件中加一个自动加载 $this->load->helper('ur ...
- Mysql事务隔离级别和锁机制
一.Spring支持四种事务隔离级别: 1.ISOLATION_READ_UNCOMMITTED(读未提交):这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据. 2.ISOLAT ...
- SwiftLint:代码规范检查工具介绍
Swift-CodeStyle Checker:SwiftLint 介绍: SwiftLint 是一个用于强制检查 Swift 代码风格和规定的一个工具,基本上以 GitHub's Swift 代码风 ...
- 关于c++中的Debug以及runtime_error之segment_fault
差不多每次编一些竞赛类的程序都会至少给我报一次runtime_error(运行时错误).这或许也是广大OIer心中永远的痛.~_~ 本文主要讨论如何对runtime_error以及其中的segment ...
- Python编程菜鸟成长记--A1--03--Python 环境安装(待完成)
1.重点知识 Windows 上如何安装 Python 3 Linux 上如何安装 Python 3 Mac 上如何安装 Python 3 Windows 上如何安装 Pycharm Mac 上如何安 ...