分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > IT知识

ASP.NET CORE Linux发布工具(文件对比 只上传差异文件;自动启停WebServer命令;上传完成自动预热WebServer)

发布时间:2023-09-06 01:55责任编辑:郭大石关键词:.NETWebLinux
最近这几日在搞一个小网站:教你啊 ;(感兴趣的朋友可以来捧场,在这个网站上有任何消费我都可以退还)
由于更新频繁,手动更新特别麻烦,于是开发了这个小工具
用了一段时间,还是挺顺手的,同时.NET CoreQQ群(225982985)的群友 @亡我之心不死  也推荐我分享出来
这就把代码公布在这里,有什么问题可以联系我:

 

先看配置文件App.Config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
?<appSettings>
???<add key="ServerIPAddress" value="***.***.***.***"/>
???<add key="SSHUserName" value="***"/>
???<add key="SSHPassWord" value="*********"/> ???
???<add key="ServerPath" value="/***/***/"/>
???<add key="ClientPath" value="D:\p\JiaoNiA\code\JNA\JNA.Web\bin\Release\netcoreapp2.0\centos.7-x64\publish\"/>
???<add key="IgnorFilePatten" value="System\..+;Microsoft\..+;.+\.so" />
???<add key="HttpServerStartCommand" value="systemctl start jna.service"/>
???<add key="HttpServerStopCommand" value="systemctl stop jna.service"/>
???<add key="WebSiteUrl" value="http://www.jiaonia.com"/>
???<add key="WebSiteAssertString" value="教你啊-知识复利制造平台"/>
?</appSettings>
???<startup>
???????<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
???</startup>
</configuration>
ServerIPAddress:服务器地址,服务器环境只支持linux
SSHUserName:服务器ssh的用户名(同时也得是sftp的用户名)
SSHPassWord:服务器ssh的密码(同时也得是sftp的密码)
ServerPath:服务器WEB程序的部署路径
ClientPath:你的开发环境,VS编译之后的路径,我用的编译命令是:
dotnet publish -c release -r centos.7-x64 ??
IgnorFilePatten:由于VS编译后的文件非常多,有些文件上传一次,一辈子也不用再上传了,那么就可以在这里设置一些正则表达式,过滤这些文件,减少比对工作量(正则表达式是用分号分割的)
HttpServerStopCommand:大部分时候更新程序都需要停机更新,这个命令就是停止WebServer的命令
HttpServerStartCommand:这个命令是升级完成后启动WebServer的命令
WebSiteUrl:升级完成后,并且WebServer也成功重启了,这个程序会请求一下你的web程序的URL,用来预热程序,要不然第一次访问很慢,这个URL就是在这里设置的
WebSiteAssertString:程序访问URL,会拿到服务端响应的HTML,然后判断响应的HTML是否包含这里设置的断言,有则证明升级成功;

好,来看代码:

先看几个私有的变量:(变量用户后面的注释有说明)
 ???????static List<FileInfo> clientFileInfos = new List<FileInfo>();//用于存储本地待对比的文件
???????static List<string> IgnorFilePattens = new List<string>();//用于存储过滤器,过滤器命中的文件不用参与对比
???????static Dictionary<FileInfo,string> prepareFileInfo = new Dictionary<FileInfo, string>();//用于存储对比后待上传的文件 ???????
???????static NameValueCollection setting = ConfigurationManager.AppSettings;
再来看Main函数:(在几个关键点我都写了注释)
static void Main(string[] args)
{
???????????Console.WriteLine("开始比对文件(根据文件的修改时间)?y:开始。其他按键退出程序:");
???????????if (Console.ReadLine() != "y")
???????????{
???????????????return;
???????????}
???????????Console.WriteLine("开始比对文件...");
???????????IgnorFilePattens.AddRange(setting["IgnorFilePatten"].Split(‘;‘));//把过滤器先缓存起来
???????????getClientFileInfos(setting["ClientPath"]);//递归取本地文件,过滤器命中的文件跳过
???????????sftpCompareFile(sftpClient => ?//本地文件与服务器文件对比
???????????{
???????????????if (prepareFileInfo.Count < 1)
???????????????{
???????????????????Console.WriteLine("没有需要更新的文件,按任意键退出程序!");
???????????????????Console.ReadKey();
???????????????????return;
???????????????}
???????????????Console.WriteLine("开始停机上传文件?y:开始。其他按键退出程序:");
???????????????if (Console.ReadLine() != "y")
???????????????{
???????????????????return;
???????????????}
???????????????sshStartAndStopWebServer(() => ?//启停Web服务器
???????????????{
???????????????????foreach (var fileInfo in prepareFileInfo.Keys)
???????????????????{
???????????????????????using (var fileStream = fileInfo.OpenRead())
???????????????????????{
???????????????????????????sftpClient.BufferSize = 6 * 1024;
???????????????????????????sftpClient.UploadFile(fileStream, prepareFileInfo[fileInfo],true); ?//上传文件
???????????????????????}
???????????????????????Console.WriteLine("上传完成:" + prepareFileInfo[fileInfo]);
???????????????????}
???????????????});
???????????????Thread.Sleep(918); ??//留给服务器喘息的时间
???????????????Console.WriteLine("开始请求目标网站...");
???????????????var html = GetHtml(setting["WebSiteUrl"]); ??//请求Web的URL
???????????????if (html.Contains(setting["WebSiteAssertString"])) ?//判断断言是否命中
???????????????{
???????????????????Console.WriteLine("升级成功,按任意键退出程序");
???????????????}
???????????????else
???????????????{
???????????????????Console.WriteLine("升级失败,请联系管理员!按任意键退出程序!");
???????????????}
???????????????Console.ReadKey();
???????????});
}

接下来,我们一点一点的看main函数里的几个关键点:
先看递归取本地文件,过滤器命中的文件跳过
 ???????static void getClientFileInfos(string path)
???????{
???????????var directoryPaths = Directory.GetDirectories(path);
???????????foreach (var directoryPath in directoryPaths)
???????????{
???????????????getClientFileInfos(directoryPath); ?//递归,自己调自己
???????????}
???????????var filePaths = Directory.GetFiles(path);
???????????foreach(var filePath in filePaths)
???????????{
???????????????var fi = new FileInfo(filePath);
???????????????var flag = false;
???????????????foreach(var patten in IgnorFilePattens)
???????????????{
???????????????????flag = Regex.IsMatch(fi.Name, patten);
???????????????????if (flag)
???????????????????{
???????????????????????break; ?//有一个过滤器命中,则不用管其他过滤器了
???????????????????}
???????????????}
???????????????if (flag)
???????????????{
???????????????????continue; //命中的文件,则跳过
???????????????}
???????????????clientFileInfos.Add(fi);
???????????}
???????}
 
本地文件与服务器文件对比:(按最后一次修改时间对比)
static void sftpCompareFile(Action<SftpClient> actor)
{
???using (var client = new SftpClient(setting["ServerIPAddress"], setting["SSHUserName"], setting["SSHPassWord"]))
???{
???????client.Connect();
???????foreach (var fileInfo in clientFileInfos)
???????{
???????????var subName = fileInfo.FullName.Remove(0, setting["ClientPath"].Length);
???????????if (subName.StartsWith("\\"))
???????????{
???????????????subName = subName.Remove(0, 1);
???????????}
???????????subName = subName.Replace(‘\\‘, ‘/‘);
???????????var serverPath = setting["ServerPath"] + subName;//前面几行代码都是为了拿到该文件在服务端的绝对路径,配置里的serverPath必须以/结尾,此处不做校验;
???????????var flag = client.Exists(serverPath);
???????????if (!flag)
???????????{
???????????????prepareFileInfo.Add(fileInfo, serverPath); //如果服务端不存在这个文件,则这个文件是肯定要上传上去的,注意:这里没管目录存在不存在
???????????????Console.WriteLine("待上传文件:" + subName);
???????????}
???????????else
???????????{
???????????????var dt = client.GetLastWriteTime(serverPath);
???????????????if (dt < fileInfo.LastWriteTime) ?//文件最后一次更新时间比较,本地的时间比服务端的时间新,则需要上传
???????????????{ ???????????????????????????
???????????????????prepareFileInfo.Add(fileInfo, serverPath);
???????????????????Console.WriteLine("待上传文件:" + subName);
???????????????}
???????????}
???????} ???????????????
???????actor(client);
???}
}
 
再来看启停Web服务器的代码:(就是直接执行配置文件中的命令,没什么特别的)
static void sshStartAndStopWebServer(Action actor)
{
???using (var sshclient = new SshClient(setting["ServerIPAddress"], setting["SSHUserName"], setting["SSHPassWord"]))
???{
???????sshclient.Connect();
???????using (var cmd = sshclient.CreateCommand(setting["HttpServerStopCommand"]))
???????{
???????????cmd.Execute();
???????????Console.WriteLine("停用HttpServer");
???????}
???????actor();
???????using (var cmd = sshclient.CreateCommand(setting["HttpServerStartCommand"]))
???????{
???????????cmd.Execute();
???????????Console.WriteLine("启用HttpServer");
???????}
???????sshclient.Disconnect();
???}
}
 
请求HTML的代码
static string GetHtml(string url)
{
???HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
???request.Timeout = 16 * 1000;
???HttpWebResponse response = request.GetResponse() as HttpWebResponse;
???Stream stream = response.GetResponseStream();
???StreamReader reader = new StreamReader(stream, Encoding.UTF8);
???string html = reader.ReadToEnd();
???stream.Close();
???return html;
}
 

这个项目用到了一个关键的库:SSH.NET
在这里向作者致敬!

感兴趣的朋友,也可以加我的QQ群沟通:51021155


ASP.NET CORE Linux发布工具(文件对比 只上传差异文件;自动启停WebServer命令;上传完成自动预热WebServer)

原文地址:https://www.cnblogs.com/liulun/p/9066493.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved