使用Jenkins实现Windows服务器下C#应用程序发布
背景
在现代化的软件开发流程中,持续集成和持续部署(CI/CD)已经成为不可或缺的一部分。
Jenkins作为一款开源的自动化运维工具,能够帮助我们实现这一目标。
本文将详细介绍如何在Windows服务器下使用Jenkins来自动化发布C#应用程序。
下载与安装
访问官方网站 https://www.jenkins.io/zh/download/。

点击上图红框中的windows,则会下载windows安装包jenkins.msi,拷贝到服务器,双击进行安装。

安装环节会提示选择JDK,要求版本17或21,下载一个17版本的JDK,放到磁盘目录,填写对应路径即可。

初始化
使用谷歌浏览器,访问http://localhost:38080/,打开初始化界面,如下图:

按照提示找到管理员密码,填充后点击继续按钮,弹出如下界面:

因服务器无法访问公网,所以显示离线,点击跳过插件安装,进入创建管理员账号界面,如下图:

点击“保存并完成”按钮,弹出提示,如下图:

再点击“保存并完成”按钮,提示安装完成,Jenkins就绪,如下图:

此时已完成Jenkins的初始化工作,并创建了管理员账号。
登录
使用ip地址+默认的38080端口访问,进入登录页面,如下图所示:

使用初始化过程中创建的账号及密码,登录,进入系统首页。

插件安装
Jenkins采用了内核+插件的模式来保持系统功能的扩展性,大量功能是通过插件来完成的。
服务器如能直接访问公网环境,直接使用在线插件管理即可,可以方便地下载、安装、更新、卸载等操作。

如服务器无法直接访问公网,则插件需要采用离线安装的方式,以常用的使用SSH协议传输文件到远程服务器的插件Publish Over SSH为例,步骤如下:
- 访问插件地址:https://plugins.jenkins.io/publish-over-ssh/releases/

- 点击上图中的版本号,下载对应该版本的文件 publish-over-ssh.hpi。
- 通过如下菜单和功能,上传插件后安装。

点击Deploy按钮后,提示该插件安装成功,但是有报错,查看installed plugins,是因为该插件有其他四个依赖插件需要安装,如下图:

按同样方法安装上述依赖的插件,发现还有进一步的依赖,如下图:

继续上述过程,前后一共下载11个插件,且有2个插件需要版本升级,如下图:

将所有依赖的插件都安装后,重启jenkins,进入已安装插件列表,显示所有插件无报错,正常加载状态。

以上方式过于繁琐,安装1个插件耗时长,工作量大,推荐更简便的方式,在能连接公网的电脑上安装同版本的Jenkins,将所需插件都安装完成后,将C:\ProgramData\Jenkins.jenkins\plugins目录下的所有文件,拷贝到内网服务器对应目录下覆盖,然后重启Jenkins生效。
SSH安装
要实现远程文件拷贝,仅仅在Jenkins服务器上安装插件是不够的,还需要在程序运行的远程服务器上安装一个SSH服务端,这里推荐OpenSSH。
OpenSSH 是一款用于安全远程连接和计算机管理的工具套件,它通过加密技术来保障通信安全,其主要功能包括远程登录、命令执行、文件传输和端口转发等。
OpenSSH 包含客户端和服务器两部分,其中:
- 客户端:用于连接远程服务器。
- 服务器:在远程服务器上运行,接受客户端的连接请求。
OpenSSH 最初是为 Linux 系统开发的,现在也支持包括 Windows 和 macOS 在内的多种操作系统。
windows Server 2016需要单独下载OpenSSH-Win64-v9.8.1.0.msi并安装,windows Server2019及以上服务器直接通过添加服务器功能的方式来实现,参考地址:https://learn.microsoft.com/zh-cn/windows-server/administration/openssh/openssh_install_firstuse?utm_source=ld246.com&eqid=ccf6b3510033b2e9000000026577e875&tabs=gui&pivots=windows-server-2019https://github.com/PowerShell/Win32-OpenSSH/releases
远程服务器配置
我们的目的是通过Jenkins实现程序的发布,因此准备工作之一就是维护一下程序运行的远程服务器地址、身份认证等信息。
访问Manage Jenkins>System,拉到最下方的SSH Servers区域,如下图所示:
点击上图中的Add按钮,添加远程服务器信息,如下:

输入名称、ip地址、服务器操作系统用户名和密码,点击右下角的测试按钮,可验证连通性,最后点击保存按钮。
重复上面步骤,添加另一台服务器219。
实战案例——备份
程序发布具有一定风险性,发布过程中出错或者发布后验证环节发现问题,且短时间内无法解决时,需要回滚到先前版本,因此通常在发布之前需要进行备份。
传统手工操作模式是将程序目录拷贝到备份目录,我们使用Jenkins来实现一键备份功能。
任务配置
在Jenkins首页,点击左侧导航中的New Item菜单,如下图所示:

输入名称,创建一个自由风格的任务,如下:

进入配置页面,在构建步骤中选择**Send files or execute commands over SSH**,然后指定批处理脚本的位置,如下图所示:

最后点击保存按钮。
批处理脚本编制
在远程服务器219上,编制批处理脚本如下:
@echo off
:: 设置源文件夹和目标备份文件夹路径
set "sourceFolder=D:\LimsWebApi"
set "backupFolderBase=D:\dev\backup\LimsWebApi":: 获取当前日期和时间
for /f "tokens=2 delims==" %%a in ('wmic os get localdatetime /value') do set datetime=%%a
set "year=%datetime:~0,4%"
set "month=%datetime:~4,2%"
set "day=%datetime:~6,2%"
set "hour=%datetime:~8,2%"
set "minute=%datetime:~10,2%"
set "second=%datetime:~12,2%":: 创建目标备份文件夹名称
set "backupFolder=%backupFolderBase%\Backup_%year%%month%%day%_%hour%%minute%%second%":: 创建目标备份文件夹
if not exist "%backupFolder%" mkdir "%backupFolder%":: 复制文件到目标备份文件夹
xcopy "%sourceFolder%\*" "%backupFolder%" /E /I /Y
其主要逻辑是设置要备份的目录,然后根据脚本执行时间生成备份文件夹名称,放到预定义的位置,拷贝所有文件夹和文件。
任务执行
在任务详情页面,点击构建,如下图:

点击上图左下角的构建记录,通过Console Output可以看到执行过程及结果,如下图:

多台备份
上面过程展示了单台服务器应用程序的备份,可以在任务配置中设置多台备份,特别是在集群部署的应用场景下。
我们修改上面的任务配置,增加220服务器的备份,如下:

再次执行任务,控制台输出如下:

实战案例——发布
传统手工操作模式需要通过远程桌面登录到各台服务器,然后分别停止IIS,拷贝覆盖发布内容,启动IIS,我们使用Jenkins来实现一键发布功能。
任务配置
在Jenkins首页,点击左侧导航中的New Item菜单,创建一个自由风格的任务,Jenkins支持复制新增功能,我们可以拷贝上文中的备份任务,在其基础上修改,如下:

修改配置,程序发布涉及到了文件传输了,如下图所示:

这里有个默认设定,源文件路径位于C:\ProgramData\Jenkins.jenkins\workspace下。

我们先执行一次,让其自动生成任务项目文件夹。
然后source files的默认起始路径,实际是C:\ProgramData\Jenkins.jenkins\workspace\lims-webapi-publish-qas。
Remote dictionary,即拷贝到远程服务器的默认起始路径是C:\Users\administrator\
我们把需要发布的程序文件放到该目录下,在Source files中使用“**”通配符代表拷贝所有的文件,包括子文件夹和子文件,在Remote dictionary输入LimsWebApi,如下图:

我们新建一个文本文档测试,执行任务,发现已经成功实现了远程文件传输,如下图:


批处理脚本编制
在远程服务器219上,编制批处理脚本如下:
@echo off
C:\Windows\System32\inetsrv\appcmd.exe stop site "LimsWebApi"
xcopy "C:\Users\administrator\LimsWebApi\*" "D:\LimsWebApi\" /E /I /Y
C:\Windows\System32\inetsrv\appcmd.exe start site "LimsWebApi"
如果该服务器上只发布了一个web站点,则可以使用net stop iisadmin和net start iisadmin 进行停止和启动整个iis服务。
不过,当该服务器上基于IIS,创建了多个web站点时,为了避免影响其他站点,使用上述脚本来实现针对特定站点的启停服务。
任务执行
在任务详情页面,点击构建,使用Console Output可以看到执行过程及结果,如下图:

实战优化——通过视图功能分离测试与生产任务
虽然我们可以通过后缀名的方式,来区分测试还是生产,但是放在同一个列表中,容易误操作,如下图所示:

我们可以使用Jenkins自带的视图功能,将测试与生产环境分离,如下图:

创建测试视图QAS,如下图:

勾选需要放到该视图中的任务,如下图:

保存后,效果如下:

同理,我们创建一个生产视图PRD,将生产相关的两个任务放进去,如下图:

通过该方式,可以方便地分离测试与生产环境的任务,避免误操作。
实战优化——使用FTP解决文件传输问题
Jenkins放在远程服务器,发布程序的时候,读取的是该服务器上的文件,也就是还需要一个步骤,把要更新的文件,从开发电脑上拷贝到Jenkins服务器上,如果这一步采用远程桌面的方式,仍然有点繁琐。
一种解决思路是采用共享文件夹的模式,将Jenkins服务器的C:\ProgramData\Jenkins.jenkins\workspace目录设置为共享。

但是由于之前局域网共享会被病毒利用,域策略默认强行关闭了文件夹共享的445端口,该方式走不通。
另一种解决思路就是通过ftp协议了,直接用IIS配置一个ftp站点出来,指向上面的workspace地址,如下图所示:

然后在开发笔记本上,通过ftp协议,直接粘贴要更新的文件即可。

这样就省去了远程桌面到Jenkins服务器的麻烦,直接复制粘贴文件,然后浏览器访问Jenkins的界面,执行任务处理即可。
常见问题
403报错
进行保存操作时,报错如下:HTTP ERROR 403 No valid crumb was included in the request

这是因为安全设置问题,按照下图,进入安全设置,将默认未勾选的Enable proxy compatibility勾选上,然后点击保存按钮,如下图:

最后,还需要重新加载一下配置使其生效。

相关文章:
使用Jenkins实现Windows服务器下C#应用程序发布
背景 在现代化的软件开发流程中,持续集成和持续部署(CI/CD)已经成为不可或缺的一部分。 Jenkins作为一款开源的自动化运维工具,能够帮助我们实现这一目标。 本文将详细介绍如何在Windows服务器下使用Jenkins来自动化发布C#应用…...
蓝桥杯练习代码
一、最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 ""。 示例 1: 输入:strs = ["flower","flow","flight"] 输出:"fl"示例 2: 输入:strs = ["dog",&q…...
算法-二叉树篇11-左叶子之和
左叶子之和 力扣题目链接 题目描述 给定二叉树的根节点 root ,返回所有左叶子之和。 解题思路 层次遍历的时候,保留每层第一个节点并相加即可。 题解 class Solution { public:int sumOfLeftLeaves(TreeNode* root) {if(root NULL){return 0;}re…...
[java基础-JVM篇]1_JVM自动内存管理
JVM内存管理涉及但不限于类加载、对象分配、垃圾回收等,本篇主要记录运行时数据区域与对象相关内容。 内容主要来源《深入理解Java虚拟机:JVM高级特性与最佳实践》与官方文档,理解与表述错漏之处恳请各位大佬指正。 目录 运行时数据区域 栈 栈…...
Junit框架缺点
JUnit 是 Java 生态中最流行的单元测试框架,广泛应用于单元测试和集成测试中。尽管它功能强大且易于使用,但也存在一些缺陷和局限性。以下是 JUnit 的主要缺点: 1. 功能相对固定 问题:JUnit 的核心功能相对固定,缺乏灵…...
机器学习数学基础:34.克隆巴赫α系数
克隆巴赫α系数(Cronbach’s Alpha)超详细教程 专为小白打造,零基础也能轻松学会! 一、深度理解α系数 克隆巴赫α系数(Cronbach’s Alpha)是在评估测验质量时极为关键的一个指标,主要用于衡量…...
【Linux】vim 设置
【Linux】vim 设置 零、起因 刚学Linux,有时候会重装Linux系统,然后默认的vi不太好用,需要进行一些设置,本文简述如何配置一个好用的vim。 壹、软件安装 sudo apt-get install vim贰、配置路径 对所有用户生效: …...
JavaScript系列(90)--前端脚手架开发
前端脚手架开发 🛠️ 前端脚手架是现代前端开发流程中的重要工具,它能够帮助开发者快速初始化项目结构、配置开发环境、设置构建流程,从而提高开发效率和标准化项目结构。本文将详细介绍前端脚手架的开发原理、实现方式以及最佳实践。 脚手…...
工程实践中常见的几种设计模式解析及 C++ 实现
工程实践中常见的几种设计模式解析及 C 实现 在软件工程中,设计模式是一种通用的解决方案,用于解决常见问题和优化代码结构。它们通过提供一种规范化的编程思想,帮助开发者写出更高效、可维护和可扩展的代码。本文将介绍几种在工程实践中常见…...
基于Python+django+mysql旅游数据爬虫采集可视化分析推荐系统
2024旅游推荐系统爬虫可视化(协同过滤算法) 基于Pythondjangomysql旅游数据爬虫采集可视化分析推荐系统 有文档说明 部署文档 视频讲解 ✅️基于用户的协同过滤推荐算法 卖价就是标价~ 项目技术栈 Python语言、Django框架、MySQL数据库、requests网络爬虫…...
Oracle 12c Docker安装问题排查 sga_target 1536M is too small
一、问题描述 在虚拟机环境(4核16GB内存)上部署 truevoly/oracle-12c 容器镜像时,一切运行正常。然而,当在一台 128 核 CPU 和 512GB 内存的物理服务器上运行时,容器启动时出现了 ORA-00821 等错误,提示 S…...
es-head(es库-谷歌浏览器插件)
1.下载es-head插件压缩包,并解压缩 2.谷歌浏览器添加插件 3.使用...
C++大整数类的设计与实现
1. 简介 我们知道现代的计算机大多数都是64位的,因此能处理最大整数为 2 64 − 1 2^{64}-1 264−1。那如果是超过了这个数怎么办呢,那就需要我们自己手动模拟数的加减乘除了。 2. 思路 我们可以用一个数组来存储大数,数组中的每一个位置表…...
Linux网络基础(协议 TCP/IP 网络传输基本流程 IP VS Mac Socket编程UDP)
文章目录 一.前言二.协议协议分层分层的好处 OSI七层模型TCP/IP五层(或四层)模型为什么要有TCP/IP协议TCP/IP协议与操作系统的关系(宏观上是如何实现的)什么是协议 三.网络传输基本流程局域网(以太网为例)通信原理MAC地址令牌环网 封装与解包分用 四.IP地址IP VS Mac地址 五.So…...
Web开发:ORM框架之使用Freesql的导航属性
一、什么时候用导航属性 看数据库表的对应关系,一对多的时候用比较好,不用多写一个联表实体,而且查询高效 二、为实体配置导航属性 1.给关系是一的父表实体加上: [FreeSql.DataAnnotations.Navigate(nameof(子表.子表关联字段))]…...
NLP07-朴素贝叶斯问句分类之数据集加载(1/3)
一、概述 数据集加载(Dataset Loading)是机器学习、自然语言处理(NLP)等领域中的一个重要步骤,指的是将外部数据(如文件、数据库、网络接口等)加载到程序中,以便进行后续处理、分析…...
Rk3568驱动开发_点亮led灯(手动挡)_5
1.MMU简介 完成虚拟空间到物理空间的映射 内存保护设立存储器的访问权限,设置虚拟存储空间的缓冲特性 stm32点灯可以直接操作寄存器,但是linux点灯不能直接访问寄存器,linux会使能mmu linux中操作的都是虚拟地址,要想访问物理地…...
LangChain构建行业知识库实践:从架构设计到生产部署全指南
文章目录 引言:行业知识库的进化挑战一、系统架构设计1.1 核心组件拓扑1.2 模块化设计原则二、关键技术实现2.1 文档预处理流水线2.2 混合检索增强三、领域适配优化3.1 医学知识图谱融合3.2 检索结果重排序算法四、生产环境部署4.1 性能优化方案4.2 安全防护体系五、评估与调优…...
Vscode编辑器:解读文件结构、插件的导入导出、常用快捷键配置技巧及其常见问题的解决方案
一、文件与文件夹结构 1.文件结构 文件名作用.babelrc配置 Babel 编译选项,指定代码转译规则。.editorconfig定义项目代码格式规范,如缩进风格和空格数量等。.eslintignore列出 ESLint 忽略的文件或文件夹。.eslintrc.js配置 ESLint 的规则和插件。.gi…...
androidstudio 运行项目加载很慢,优化方法
一、Android Studio 运行项目加载缓慢可能由多种原因引起,以下是一些优化建议: 1. 升级硬件配置 内存:建议至少 8GB,16GB 或以上更佳。 SSD:使用 SSD 替代 HDD 以加快读写速度。 CPU:多核处理器有助于提…...
Vue性能翻倍秘籍
导读:某电商大促因工程化缺失导致页面崩溃!本文通过双11级别流量压测,揭秘Vue项目性能优化的6大核心策略,涵盖构建提速、首屏优化、SSR实战等全链路方案。 工程化缺失引发的灾难现场 血泪案例: 某电商大促活动因工程化…...
线性回归 (Linear Regression)案例分析1
广告费用与产品销量 工欲善其事必先利其器数据分析1. 检查缺失值、异常值3. 散点图查看特征、响应相关性3. 热力图查看特征、响应相关性 特征工程1、导入必要工具包2、读取数据3、数据标准化4、保存特征工程的结果到文件,供机器学习模型使用 模型选择读取数据数据准…...
uni-app集成sqlite
Sqlite SQLite 是一种轻量级的关系型数据库管理系统(RDBMS),广泛应用于各种应用程序中,特别是那些需要嵌入式数据库解决方案的场景。它不需要单独的服务器进程或系统配置,所有数据都存储在一个单一的普通磁盘文件中&am…...
策略模式环境类的实现方式对比
文章目录 1、策略模式2、聚合策略类实现方式一3、聚合策略类实现方式二4、对比5、补充:ApplicationContextAware接口 1、策略模式 近期工作中,需要处理4.x和5.x两个版本的数据,所以自然想到的是策略模式,写一个抽象类,…...
Node.js 登录鉴权
目录 Session express-session 配置 express-session 函数 ts 要配置声明文件 express-session.d.ts express-session 使用 express-session 带角色 Token 什么是 JWT token jsonwebtoken 使用 jsonwebtoken 带角色 Session express 使用 express-session 管理会话&…...
【c++】【线程池】固定式线程池(FixedThreadPool)
【c】【线程池】固定式线程池(FixedThreadPool) 1属性 1.1 Task可调用对象 使用 function 包装器和using类型重命名 设置一个Task的可调用对象(可理解为函数指针) 这个Task也就是我们的任务 using Task std::function<void(void)>;定义了一个…...
高可用、高性能、负载均衡集群的区别
维度高可用集群高性能集群负载均衡集群核心目标服务持续可用,减少停机加速计算任务,提升处理能力请求分发算法、健康检查关键技术冗余、心跳检测、鼓掌转移并行计算、高速网络、分布式存储请求分发算法、健康检查典型应用数据库主从切换、关键业务系统科…...
Docker 与 Serverless(无服务器架构)
Serverless(无服务器架构) 是一种新的云计算架构,它通过让开发者专注于业务逻辑而无需管理服务器基础设施,来简化应用的开发和部署。Serverless 模型通常由云服务提供商管理基础设施的所有方面,而开发者只需提供代码和…...
mac 下 java 调用 gurobi 不能加载 jar
在 mac 电脑中的 java 始终不能加载 gurobi 的 jar 包,java 的开发软件 eclipse,idea 总是显示找不到 gurobi 的 jar 包,但是 jar 包明明就在那里。 摸索了三个小时,最后发现原因竟然是: jar 包太新,替换…...
halcon三维点云数据处理(二十七)remove_bin_for_3d_object_localization
目录 一、remove_bin_for_3d_object_localization代码第一部分二、remove_bin_for_3d_object_localization代码第二部分三、效果图一、remove_bin_for_3d_object_localization代码第一部分 1、读图构建3D模型。 2、一次二值化选取区域。 3、一次和背景差值选取区域。 4、在二维…...
