zoukankan      html  css  js  c++  java
  • netcore一键nssm发布为windows服务

    AntDeploy

    是我开发一款开源一键部署工具包

    发布功能支持:

    • docker容器一键部署
    • docker镜像一键发布
    • 支持iis一键部署
    • windows服务一键部署
    • linux服务一键部署
    • 支持增量发布
    • 支持一键回滚
    • 支持点火
    • 支持选择特定文件发布
    • 支持查看发布记录

    一个issue

    前两天有一个使用者给我反馈了一个issue

    image

    他是用asp5.0开发了一个web程序,然后用AntDeploy来部署,
    由于AntDeploy部署时读取服务的安装路径,然后进行更新。
    但是针对nssm部署的服务有一个特点,执行路径是nssm.exe,如下图:

    image

    那么AntDeploy在更新部署的时候会更新到nssm.exe所在的目录了。

    解决思路

    nssm是一个开源c语言写的软件,大概只有300kb,可以很方便的把程序安装成一个windows服务。

    nssm就像是一个服务管理器,windows服务启动的时候 会调用nssm.exe传入serviceName、然后nssm.exe会根据serviceName拿到配置的实际要运行的文件。

    查了下nssm官网

    可以根据命令

    nssm get <serviceName> Application
    

    获取实际要执行的程序地址

    那么要想要兼容第一次是由nssm.exe部署,后面用AntDeploy发布的场景,则需要

      1. 根据调用nssm的命令拿到真实路径
      1. 根据真实路径进行部署

    image

    既然是开源软件,就让这位仁兄来帮我写这部分代码吧

    image

    果然这位仁兄战斗力可以,很快就搞定了

    image

    image

    开源就是要参与进来 这也是我热爱开源的原因

    扩展nssm发布windows功能

    上面虽然已经解决了:首次用nssm发布,后面用AntDeploy来更新的场景。

    还需要解决掉首次无法使用nssm发布的功能。

    我觉得有必要加这个功能,来完成nssm发布windows服务的闭环

    好处有:

    一般按照微软开发winfows服务的标准的话 是需要引入包:Microsoft.Extensions.Hosting.WindowsServices
    
    但是用nssm可以不需要引入。
    
    所以在netcore开发web的场景使用nssm安装为windows服务很方便
    
    而且使用nssm安装的另外一个优点是可以指定启动参数? 比如 --urls=http://*:10007
    

    开始开发

    1. 客户端 增加入口可以使用nssm

    image

    2. ageng端增加 nssm

    在windows场景下才 作为内嵌资源。针对linux场景不需要。

    image

    在启动的时候释放出来:

    
    var nssmSavePath = Path.Combine(Startup.RootPath, "nssm.exe");
    if (File.Exists(nssmSavePath))
    {
        return;
    }
    Assembly assembly = typeof(AntDeployAgentWindowsService).Assembly;
    using (Stream stream = assembly.GetManifestResourceStream("AntDeployAgentService.nssm.exe"))
    {
        if (stream != null)
        {
            using (var fileStream = File.Create(nssmSavePath))
            {
                stream.Seek(0, SeekOrigin.Begin);
                stream.CopyTo(fileStream);
            }
        }
    }
    
    if (!File.Exists(nssmSavePath))
    {
        throw new FileNotFoundException(nssmSavePath + " not found");
    }
    
    

    和客户端约定了2个新传参:

    • useNssm 客户端是否选择采用nssm来部署服务
    • param 服务运行的参数

    agent端处理第一次用nssm部署

    主要用到了下面几个命令:

    nssm install <serviceName> "<实际执行文件的完整路径>"
    
    nssm set <serviceName> AppDirectory "<实际执行文件所在的目录>"
    
    nssm set <serviceName> Description "<服务的描述>"
    
    nssm set <serviceName> AppParameters "<服务运行指定的参数>"
    
    nssm start <serviceName>
    

    封装一个方法来执行nssm命令

    public static bool RunExternalExe(string projectPath, string arguments, Action<string> logger)
    {
        Process process = null;
        try
        {
    
            if (string.IsNullOrEmpty(arguments))
            {
                throw new ArgumentException(nameof(arguments));
            }
    
            process = new Process();
    
            process.StartInfo.FileName = projectPath;
            process.StartInfo.Arguments = arguments;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.Verb = "runas";
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.Start();
            process.OutputDataReceived += (sender, args) =>
            {
                if (!string.IsNullOrWhiteSpace(args.Data))
                {
                    logger(args.Data);
                }
            };
            process.BeginOutputReadLine();
    
            process.ErrorDataReceived += (sender, data) =>
            {
                if (!string.IsNullOrWhiteSpace(data.Data)) logger(data.Data);
            };
            process.BeginErrorReadLine();
            process.WaitForExit();
            //var err = process.StandardError.ReadToEnd();
            return process.ExitCode == 0;
        }
        catch (Exception ex)
        {
            return false;
        }
        finally
        {
            process?.Dispose();
        }
    }
    

    以aspnet5的web测试
    完整的运行效果是:

    image

    服务部署成功

    image

    访问成功

    image

    成功物

    插件最新版: v7.32

    agent最新版:v6.9

    源码地址:https://github.com/yuzd/AntDeployAgent

    交流QQ群:488312978


    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,转载文章之后须在文章页面明显位置给出作者和原文连接,谢谢。
  • 相关阅读:
    当统计信息不准确时,CBO可能产生错误的执行计划,并在10053 trace中找到CBO出错的位置示例
    ruby class_eval的使用
    ruby修改TXT文件
    ruby格式化
    VIM常用命令集合
    Watir::IE.attach与IE7选项卡的设置关系
    ruby 连接mysql数据库
    AutoIT删除Internet临时文件
    watir学习之—如何遍历页面所有的超链接
    watir如何取到元素的css属性
  • 原文地址:https://www.cnblogs.com/yudongdong/p/15085355.html
Copyright © 2011-2022 走看看