博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET CORE Linux发布工具(文件对比 只上传差异文件;自动启停WebServer命令;上传完成自动预热WebServer)...
阅读量:5785 次
发布时间:2019-06-18

本文共 6633 字,大约阅读时间需要 22 分钟。

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

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

用了一段时间,还是挺顺手的,同时.NET CoreQQ群(225982985)的群友 @亡我之心不死  也推荐我分享出来

这就把代码公布在这里,有什么问题可以联系我:

 

28932-20180521115909975-63647351.png

 

 

先看配置文件App.Config:

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
clientFileInfos = new List
();//用于存储本地待对比的文件 static List
IgnorFilePattens = new List
();//用于存储过滤器,过滤器命中的文件不用参与对比 static Dictionary
prepareFileInfo = new Dictionary
();//用于存储对比后待上传的文件 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
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;}

 

 

这个项目用到了一个关键的库:

在这里向作者致敬!

 

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

 

 

转载地址:http://avvyx.baihongyu.com/

你可能感兴趣的文章
位图排序
查看>>
nice team(第一次会议)
查看>>
_BV()
查看>>
So easy:PHP array_multisort()函数
查看>>
sql日期格式化
查看>>
一个Web项目中实现多个数据库存储数据并相互切换用过吗?
查看>>
Android腾讯微博开发之随机字符串与签名实现
查看>>
js 随机数
查看>>
(转)jenkins构建触发器定时任务Build periodically和Poll SCM
查看>>
在使用MVC对象传参的心得
查看>>
Android 安全退出应用程序的方法总结
查看>>
var、let、const区别
查看>>
ASP.NET安全问题--ASP.NET安全架构
查看>>
【Oracle】oracle之listagg分析函数
查看>>
f5创建VS
查看>>
cobbler 修改 distro_signatures.json
查看>>
学完微型服务器(Tomcat)对其工作流程的理解,自己着手写个简单的tomcat
查看>>
JSONOBJECT
查看>>
小Z的课堂检测(test)
查看>>
C#学习笔记四(LINQ,错误和异常,异步编程,反射元数据和动态编程)
查看>>