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

posted @ 2021-07-31 21:41  俞正东  阅读(1052)  评论(2编辑  收藏  举报