最近这几日在搞一个小网站:教你啊 ;(感兴趣的朋友可以来捧场,在这个网站上有任何消费我都可以退还)

由于更新频繁,手动更新特别麻烦,于是开发了这个小工具

用了一段时间,还是挺顺手的,同时.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)的更多相关文章

  1. ASP.NET Core Linux 发布

    这篇博客参考了以下文章: 1.http://www.cnblogs.com/ants/p/5732337.html 2.http://www.linuxidc.com/Linux/2016-11/13 ...

  2. Asp.Net Core Linux环境下 找不到配置文件、静态文件的问题

    直接发布会找不到配置文件,和静态文件.需要先cd到项目文件夹,然后在发布.

  3. Asp.net Core 打包发布 (Linux+Nginx)

    如果你觉得如下这些文章对你有帮助,请点击链接支持作者原创 http://www.cnblogs.com/savorboard/ .Net Core SDK 命令介绍   前言 本篇主要介绍 asp.n ...

  4. ASP.NET Core 网站发布到Linux服务器(转)

    出处;ASP.NET Core 网站发布到Linux服务器 长期以来,使用.NET开发的应用只能运行在Windows平台上面,而目前国内蓬勃发展的互联网公司由于成本的考虑,大量使用免费的Linux平台 ...

  5. 将asp.net core站点发布到IIS上遇到的问题

    今天第一次将整个 asp.net core 站点发布到 IIS 上,以前都是发布到 Linux 服务器上. 开始使用 dotnet publish -c release 命令发布,用浏览器访问站点时出 ...

  6. ASP.NET Core IIS发布

    ASP.NET Core应用发布到IIS 官网教程地址:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/publish-to-iis?vi ...

  7. 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 ...

  8. ASP.NET Core 网站发布到Linux服务器

    长期以来,使用.NET开发的应用只能运行在Windows平台上面,而目前国内蓬勃发展的互联网公司由于成本的考虑,大量使用免费的Linux平台,这就使得.NET空有一身绝技但无法得到广大的施展空间,.N ...

  9. ASP.NET Core 程序发布到Linux(Centos7)爬坑实战

    前言 前阶段弄了个Linux系统想倒腾倒腾.NET Core,结果看了下网上的资料,大部分都是过期的,走了不少弯路,不过还好,今下午总算捣鼓出来了.Linux命令太多了,唉.血的教训:安装一定要看官网 ...

随机推荐

  1. Oracle E-Business Suite Maintenance Guide Release 12.2(Patching Procedures)

    更多内容参考: http://docs.oracle.com/cd/E51111_01/current/acrobat/122ebsmt.zip Preparing for Patching For ...

  2. LeetCode之“动态规划”:Maximal Square && Largest Rectangle in Histogram && Maximal Rectangle

    1. Maximal Square 题目链接 题目要求: Given a 2D binary matrix filled with 0's and 1's, find the largest squa ...

  3. windows的服务中的登录身份本地系统账户、本地服务账户和网络服务账户修改

    以一个redis服务为例: 一个redis注册服务后一般是网络服务账户,但是当系统不存在网络服务账户时,就会导致redis服务无法正常启动.接下来修改redis服务的登录身份. cmd下输入如下命令: ...

  4. RTMPdump(libRTMP) 源代码分析 6: 建立一个流媒体连接 (NetStream部分 1)

    ===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...

  5. 【编程练习】收集的一些c++代码片,算法排序,读文件,写日志,快速求积分等等

    写日志: class LogFile { public: static LogFile &instance(); operator FILE *() const { return m_file ...

  6. HBase 索引创建

    本文参考了文"mysql索引背后的数据结构及算法原理",之所以还要摘录,主要是为了形成hbase索引研究的开篇,弄明白什么索引的本质,如有版权问题,请及时通知. 索引的本质 索引是 ...

  7. The 13th tip of DB Query Analyzer, powerful processing EXCEL file

    The 13thtip of DB Query Analyzer, powerful processing EXCEL file MA Genfeng (Guangdong UnitollServic ...

  8. 从小故事来谈nginx负载均衡

    负载均衡 负载均衡是任何一个有一定规模的互联网企业都会考虑的问题,负载方式很多,有依靠硬件实现的,也有依靠软件实现负载的. 今天来聊聊使用软件来负载的方式 你可能听过各自负载的方式,比如常见的ngin ...

  9. 赋给个人账户sudo的全部root执行权限

    sudo visudo 输入root账户密码后,会自动打开sudoers文件编辑 在root     ALL=(ALL)    ALL此行下增加一行 user ALL=(ALL)    NOPASSW ...

  10. mongodb3.6 副本集(三)mongodb 如何做数据备灾

    前言 个人理解,副本集一个主要作用就是当Master库出现故障,其中的一个salve从库会被选举出来成为新的Master.框架图如下: 其中,选举者是不参与数据存储的,它的作用只是为了选举出新的Mas ...