ASP.NET CORE Linux发布工具(文件对比 只上传差异文件;自动启停WebServer命令;上传完成自动预热WebServer)
最近这几日在搞一个小网站:教你啊 ;(感兴趣的朋友可以来捧场,在这个网站上有任何消费我都可以退还)
由于更新频繁,手动更新特别麻烦,于是开发了这个小工具
用了一段时间,还是挺顺手的,同时.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)的更多相关文章
- ASP.NET Core Linux 发布
这篇博客参考了以下文章: 1.http://www.cnblogs.com/ants/p/5732337.html 2.http://www.linuxidc.com/Linux/2016-11/13 ...
- Asp.Net Core Linux环境下 找不到配置文件、静态文件的问题
直接发布会找不到配置文件,和静态文件.需要先cd到项目文件夹,然后在发布.
- Asp.net Core 打包发布 (Linux+Nginx)
如果你觉得如下这些文章对你有帮助,请点击链接支持作者原创 http://www.cnblogs.com/savorboard/ .Net Core SDK 命令介绍 前言 本篇主要介绍 asp.n ...
- ASP.NET Core 网站发布到Linux服务器(转)
出处;ASP.NET Core 网站发布到Linux服务器 长期以来,使用.NET开发的应用只能运行在Windows平台上面,而目前国内蓬勃发展的互联网公司由于成本的考虑,大量使用免费的Linux平台 ...
- 将asp.net core站点发布到IIS上遇到的问题
今天第一次将整个 asp.net core 站点发布到 IIS 上,以前都是发布到 Linux 服务器上. 开始使用 dotnet publish -c release 命令发布,用浏览器访问站点时出 ...
- ASP.NET Core IIS发布
ASP.NET Core应用发布到IIS 官网教程地址:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/publish-to-iis?vi ...
- Windows平台部署 Asp.Net Core 3.1.0,将 ASP.NET Core 应用发布到 IIS ,使用 IIS 在 Windows 上托管 ASP.NET Core
第一部分:本教程介绍如何在 IIS 服务器上托管 ASP.NET Core 应用. 官方文档地址:https://docs.microsoft.com/zh-cn/aspnet/core/tutori ...
- ASP.NET Core 网站发布到Linux服务器
长期以来,使用.NET开发的应用只能运行在Windows平台上面,而目前国内蓬勃发展的互联网公司由于成本的考虑,大量使用免费的Linux平台,这就使得.NET空有一身绝技但无法得到广大的施展空间,.N ...
- ASP.NET Core 程序发布到Linux(Centos7)爬坑实战
前言 前阶段弄了个Linux系统想倒腾倒腾.NET Core,结果看了下网上的资料,大部分都是过期的,走了不少弯路,不过还好,今下午总算捣鼓出来了.Linux命令太多了,唉.血的教训:安装一定要看官网 ...
随机推荐
- 基于ARM-contexA9-Linux驱动开发:如何获取板子上独有的ID号
每个CPU,都有它固定的ID号,ID号就是这个CPU唯一的标识,它可能隐含着CPU的生产日期,版本号,型号等等,那么,在我们的这款友善之臂Tiny4412的板子上,我的这个CPU的ID又是多少呢?从我 ...
- 网站开发进阶(十一)如何将一个jsp页面嵌套在另一个页面中
如何将一个jsp页面嵌套在另一个页面中 这个在做网页中常要用到,有些通用的内容可集中放在一个页面文件中,其它要用到这些内容的页面只需要包含(引用)这个通用文件即可.这样便于维护,如果有很多网页,当通用 ...
- Auto Create Editable Copy Font(Unity3D开发之二十二)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/48318879 ...
- OpenCV——PS 图层混合算法 (四)
具体的算法原理可以参考 PS图层混合算法之四(亮光, 点光, 线性光, 实色混合) // PS_Algorithm.h #ifndef PS_ALGORITHM_H_INCLUDED #define ...
- AMDP + XLSX Workbench 报表开发模式
本文介绍了我和同事通过使用AMDP + XLSX Workbench缩短报表开发周期.分离数据查询处理逻辑和前端展示工作的经验.欢迎讨论. 前言 最近接到了一套人力资源报表的开发需求,需要以EXCEL ...
- Symmetric Tree 对称树
判断一棵二叉树是否为对称的树.如 1 / \ 2 2 / \ / \ 3 4 4 3 观察上面的树可以看出:左子树的右子树等于右子树的左子树,左子树的左子树等于右子树的右子树. 首先可以使用递归.递归 ...
- 直接执行SQL语句的快捷键是什么啊?嘎嘎
在查询中输入SQL语句后,执行语句的快捷键~ 分享到: 2009-10-23 10:59网友采纳 左键..嘿嘿,开个玩笑 你把鼠标移动到执行按钮上停一会就能看到了啊
- nginx简单安装设置
1.Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄罗斯访问量第二 ...
- FFPLAY的原理(三)
播放声音 现在我们要来播放声音.SDL也为我们准备了输出声音的方法.函数SDL_OpenAudio()本身就是用来打开声音设备的.它使用一个叫做SDL_AudioSpec结构体作为参数,这个结构体中包 ...
- node八-核心模块、包
学会查API,远比会几个API更重要. 核心模块意义 -如果只是在服务器运行javascript代码,并没有多大意义,因为无法实现任何功能>读写文件.访问网络 -Node的用处在于它本身还提供可 ...