netcore一鍵nssm釋出為windows服務

俞正東發表於2021-07-31

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

相關文章