From f1f22f2ef10a0c30fa8488ad0701d0f8710c5d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=BA=E8=83=BD=E5=A4=A7=E7=9F=B3=E5=A4=B4?= Date: Mon, 2 Dec 2024 08:38:33 +0800 Subject: [PATCH] =?UTF-8?q?[refactor]=20=E9=87=8D=E6=9E=84=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=AE=89=E8=A3=85=EF=BC=8C=E5=A4=96=E9=83=A8=E4=BC=A0?= =?UTF-8?q?=E5=85=A5=E6=9C=8D=E5=8A=A1=E6=A8=A1=E5=9E=8BServiceModel?= =?UTF-8?q?=EF=BC=8C=E7=BB=9F=E4=B8=80=E8=A7=A3=E6=9E=90=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E8=A1=8C=E5=8F=82=E6=95=B0=E3=80=82fix:=20https://github.com/N?= =?UTF-8?q?ewLifeX/NewLife.Agent/issues/22?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Command/CommandHandlerFactory.cs | 2 +- NewLife.Agent/CommandHandler/Install.cs | 41 ++++++++++++- NewLife.Agent/DefaultHost.cs | 8 +-- NewLife.Agent/IHost.cs | 8 +-- NewLife.Agent/OSXLaunch.cs | 43 +++++--------- NewLife.Agent/Procd.cs | 18 ++++-- NewLife.Agent/RcInit.cs | 26 +++++---- NewLife.Agent/SysVinit.cs | 8 +-- NewLife.Agent/Systemd.cs | 57 ++++--------------- NewLife.Agent/WindowsAutorun.cs | 13 +++-- NewLife.Agent/WindowsService.cs | 24 ++++---- Test/Properties/launchSettings.json | 8 +++ 12 files changed, 123 insertions(+), 133 deletions(-) create mode 100644 Test/Properties/launchSettings.json diff --git a/NewLife.Agent/Command/CommandHandlerFactory.cs b/NewLife.Agent/Command/CommandHandlerFactory.cs index 0c1390d..dc75b08 100644 --- a/NewLife.Agent/Command/CommandHandlerFactory.cs +++ b/NewLife.Agent/Command/CommandHandlerFactory.cs @@ -9,7 +9,7 @@ namespace NewLife.Agent.Command; public class CommandFactory { private readonly List _commandHandlerList; - private Dictionary _commandHandlerDict = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _commandHandlerDict = new(StringComparer.OrdinalIgnoreCase); /// /// 命令工厂 diff --git a/NewLife.Agent/CommandHandler/Install.cs b/NewLife.Agent/CommandHandler/Install.cs index 93fe545..1bf4ef8 100644 --- a/NewLife.Agent/CommandHandler/Install.cs +++ b/NewLife.Agent/CommandHandler/Install.cs @@ -1,4 +1,6 @@ using NewLife.Agent.Command; +using NewLife.Agent.Models; +using NewLife.Log; namespace NewLife.Agent.CommandHandler; @@ -46,15 +48,34 @@ public override void Process(String[] args) exe = dll; } + var service = new ServiceModel + { + ServiceName = Service.ServiceName, + DisplayName = Service.DisplayName, + Description = Service.Description, + FileName = exe + }; + + // 从文件名中分析工作目录 + var ss = service.FileName.Split(" "); + if (ss.Length >= 2 && ss[0].EndsWithIgnoreCase("dotnet", "java")) + { + var file = ss[1]; + if (File.Exists(file)) + service.WorkingDirectory = Path.GetDirectoryName(file).GetFullPath(); + else + service.WorkingDirectory = ".".GetFullPath(); + } + //var arg = UseAutorun ? "-run" : "-s"; var arg = "-s"; // 兼容更多参数做为服务启动,譬如:--urls - if (args.Length > 2) + if (args.Length > 1) { // 跳过系统内置参数 var list = new List(); - for (var i = 2; i < args.Length; i++) + for (var i = 1; i < args.Length; i++) { if (args[i].EqualIgnoreCase("-server", "-user", "-group")) i++; @@ -64,9 +85,23 @@ public override void Process(String[] args) list.Add(args[i]); } if (list.Count > 0) arg += " " + list.Join(" "); + + for (var i = 0; i < args.Length; i++) + { + if (args[i].EqualIgnoreCase("-user") && i + 1 < args.Length) + { + service.User = args[i + 1]; + } + if (args[i].EqualIgnoreCase("-group") && i + 1 < args.Length) + { + service.Group = args[i + 1]; + } + } } - Service.Host.Install(Service.ServiceName, Service.DisplayName, exe, arg, Service.Description); + service.Arguments = arg; + //Service.Host.Install(Service.ServiceName, Service.DisplayName, exe, arg, Service.Description); + Service.Host.Install(service); // 稍微等一下,以便后续状态刷新 Thread.Sleep(500); diff --git a/NewLife.Agent/DefaultHost.cs b/NewLife.Agent/DefaultHost.cs index fd556bc..c0e9c0e 100644 --- a/NewLife.Agent/DefaultHost.cs +++ b/NewLife.Agent/DefaultHost.cs @@ -35,13 +35,9 @@ public class DefaultHost : DisposeBase, IHost public virtual Boolean IsRunning(String serviceName) => false; /// 安装服务 - /// 服务名 - /// 显示名 - /// 文件路径 - /// 命令参数 - /// 描述信息 + /// 服务 /// - public virtual Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description) => false; + public virtual Boolean Install(ServiceModel service) => false; /// 卸载服务 /// 服务名 diff --git a/NewLife.Agent/IHost.cs b/NewLife.Agent/IHost.cs index 43131d5..981d642 100644 --- a/NewLife.Agent/IHost.cs +++ b/NewLife.Agent/IHost.cs @@ -19,13 +19,9 @@ public interface IHost Boolean IsRunning(String serviceName); /// 安装服务 - /// 服务名 - /// 显示名 - /// 文件路径 - /// 命令参数 - /// 描述信息 + /// 服务 /// - Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description); + Boolean Install(ServiceModel service); /// 卸载服务 /// 服务名 diff --git a/NewLife.Agent/OSXLaunch.cs b/NewLife.Agent/OSXLaunch.cs index a2c0997..39ea664 100644 --- a/NewLife.Agent/OSXLaunch.cs +++ b/NewLife.Agent/OSXLaunch.cs @@ -8,7 +8,7 @@ namespace NewLife.Agent; public class OSXLaunch : DefaultHost { #region 静态 - private static String _path; + private static readonly String _path; /// 是否可用 public static Boolean Available => !_path.IsNullOrEmpty(); @@ -90,41 +90,24 @@ public override Boolean IsRunning(String serviceName) } /// 安装服务 - /// 服务名 - /// 显示名 - /// 文件路径 - /// 命令参数 - /// 描述信息 + /// 服务 /// - public override Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description) + public override Boolean Install(ServiceModel service) { - if (User.IsNullOrEmpty()) - { - // 从命令行参数加载用户设置 -user - var args = Environment.GetCommandLineArgs(); - if (args.Length >= 1) - { - for (var i = 0; i < args.Length; i++) - { - if (args[i].EqualIgnoreCase("-user") && i + 1 < args.Length) - { - User = args[i + 1]; - break; - } - if (args[i].EqualIgnoreCase("-group") && i + 1 < args.Length) - { - Group = args[i + 1]; - break; - } - } - if (!User.IsNullOrEmpty() && Group.IsNullOrEmpty()) Group = User; - } - } + var serviceName = service.ServiceName; + var displayName = service.DisplayName; + var description = service.Description; + var fileName = service.FileName; + var arguments = service.Arguments; + + if (!service.User.IsNullOrEmpty()) User = service.User; + if (!service.Group.IsNullOrEmpty()) Group = service.Group; + if (!User.IsNullOrEmpty() && Group.IsNullOrEmpty()) Group = User; return Install(_path, serviceName, displayName, fileName, arguments, description, User, Group, DependOnNetwork); } - static String _template = """ + static readonly String _template = """ diff --git a/NewLife.Agent/Procd.cs b/NewLife.Agent/Procd.cs index 209caf8..bd7795f 100644 --- a/NewLife.Agent/Procd.cs +++ b/NewLife.Agent/Procd.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Text; +using NewLife.Agent.Models; using NewLife.Log; namespace NewLife.Agent; @@ -105,13 +106,18 @@ public override Boolean IsRunning(String serviceName) } /// 安装服务 - /// 服务名 - /// 显示名 - /// 文件路径 - /// 命令参数 - /// 描述信息 + /// 服务 /// - public override Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description) => Install(_path, serviceName, fileName, arguments, displayName, description); + public override Boolean Install(ServiceModel service) + { + var serviceName = service.ServiceName; + var displayName = service.DisplayName; + var description = service.Description; + var fileName = service.FileName; + var arguments = service.Arguments; + + return Install(_path, serviceName, fileName, arguments, displayName, description); + } /// 安装服务 /// system目录 diff --git a/NewLife.Agent/RcInit.cs b/NewLife.Agent/RcInit.cs index d25ff00..ac30f1b 100644 --- a/NewLife.Agent/RcInit.cs +++ b/NewLife.Agent/RcInit.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Text; +using NewLife.Agent.Models; using NewLife.Log; namespace NewLife.Agent; @@ -84,19 +85,24 @@ public override Boolean IsInstalled(String serviceName) /// public override Boolean IsRunning(String serviceName) { - var p = GetProcess(serviceName, out _); + var p = RcInit.GetProcess(serviceName, out _); return p != null && !GetHasExited(p); } /// 安装服务 - /// 服务名 - /// 显示名 - /// 文件路径 - /// 命令参数 - /// 描述信息 + /// 服务 /// - public override Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description) => Install(_path, serviceName, fileName, arguments, displayName, description); + public override Boolean Install(ServiceModel service) + { + var serviceName = service.ServiceName; + var displayName = service.DisplayName; + var description = service.Description; + var fileName = service.FileName; + var arguments = service.Arguments; + + return Install(_path, serviceName, fileName, arguments, displayName, description); + } /// 安装服务 /// system目录 @@ -256,7 +262,7 @@ public override Boolean Start(String serviceName) XTrace.WriteLine("{0}.Start {1}", Name, serviceName); // 判断服务是否已启动 - var p = GetProcess(serviceName, out _); + var p = RcInit.GetProcess(serviceName, out _); if (p != null && !GetHasExited(p)) return false; //var file = _path.CombinePath($"{serviceName}"); @@ -277,7 +283,7 @@ public override Boolean Stop(String serviceName) { XTrace.WriteLine("{0}.Stop {1}", Name, serviceName); - var p = GetProcess(serviceName, out var pid); + var p = RcInit.GetProcess(serviceName, out var pid); if (p == null) return false; try @@ -311,7 +317,7 @@ public override Boolean Restart(String serviceName) return true; } - private Process GetProcess(String serviceName, out String pid) + private static Process GetProcess(String serviceName, out String pid) { var id = 0; pid = $"{serviceName}.pid".GetFullPath(); diff --git a/NewLife.Agent/SysVinit.cs b/NewLife.Agent/SysVinit.cs index 0b9124a..5bf5756 100644 --- a/NewLife.Agent/SysVinit.cs +++ b/NewLife.Agent/SysVinit.cs @@ -55,13 +55,9 @@ public override Boolean IsRunning(String serviceName) } /// 安装服务 - /// 服务名 - /// 显示名 - /// 文件路径 - /// 命令参数 - /// 描述信息 + /// 服务 /// - public override Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description) + public override Boolean Install(ServiceModel service) { //暂不实现SysVinit服务安装 throw new NotImplementedException("SysVinit installation is not implemented."); diff --git a/NewLife.Agent/Systemd.cs b/NewLife.Agent/Systemd.cs index ebba85d..079448a 100644 --- a/NewLife.Agent/Systemd.cs +++ b/NewLife.Agent/Systemd.cs @@ -107,54 +107,21 @@ public override Boolean IsRunning(String serviceName) } /// 安装服务 - /// 服务名 - /// 显示名 - /// 文件路径 - /// 命令参数 - /// 描述信息 + /// 服务 /// - public override Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description) + public override Boolean Install(ServiceModel service) { var set = Setting; - set.ServiceName = serviceName; - set.DisplayName = displayName; - set.Description = description; - set.FileName = fileName; - set.Arguments = arguments; - - // 从文件名中分析工作目录 - var ss = fileName.Split(" "); - if (ss.Length >= 2 && ss[0].EndsWithIgnoreCase("dotnet", "java")) - { - var file = ss[1]; - if (File.Exists(file)) - set.WorkingDirectory = Path.GetDirectoryName(file).GetFullPath(); - else - set.WorkingDirectory = ".".GetFullPath(); - } - - if (set.User.IsNullOrEmpty()) - { - // 从命令行参数加载用户设置 -user - var args = Environment.GetCommandLineArgs(); - if (args.Length >= 1) - { - for (var i = 0; i < args.Length; i++) - { - if (args[i].EqualIgnoreCase("-user") && i + 1 < args.Length) - { - set.User = args[i + 1]; - break; - } - if (args[i].EqualIgnoreCase("-group") && i + 1 < args.Length) - { - set.Group = args[i + 1]; - break; - } - } - if (!set.User.IsNullOrEmpty() && set.Group.IsNullOrEmpty()) set.Group = set.User; - } - } + set.ServiceName = service.ServiceName; + set.DisplayName = service.DisplayName; + set.Description = service.Description; + set.FileName = service.FileName; + set.Arguments = service.Arguments; + set.WorkingDirectory = service.WorkingDirectory; + + set.User = service.User; + set.Group = service.Group; + if (!set.User.IsNullOrEmpty() && set.Group.IsNullOrEmpty()) set.Group = set.User; return Install(ServicePath, set); } diff --git a/NewLife.Agent/WindowsAutorun.cs b/NewLife.Agent/WindowsAutorun.cs index 2d4095b..1ac7439 100644 --- a/NewLife.Agent/WindowsAutorun.cs +++ b/NewLife.Agent/WindowsAutorun.cs @@ -72,17 +72,18 @@ public override unsafe Boolean IsRunning(String serviceName) } /// 安装服务 - /// 服务名 - /// - /// 文件路径 - /// 命令参数 - /// + /// 服务 /// #if NET5_0_OR_GREATER [SupportedOSPlatform("windows")] #endif - public override Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description) + public override Boolean Install(ServiceModel service) { + var serviceName = service.ServiceName; + var displayName = service.DisplayName; + var description = service.Description; + var fileName = service.FileName; + var arguments = service.Arguments; XTrace.WriteLine("{0}.Install {1}, {2}, {3}, {4}", GetType().Name, serviceName, displayName, fileName, arguments, description); if (!WindowsService.IsAdministrator()) return WindowsService.RunAsAdministrator("-i"); diff --git a/NewLife.Agent/WindowsService.cs b/NewLife.Agent/WindowsService.cs index 3aba6ec..794a60d 100644 --- a/NewLife.Agent/WindowsService.cs +++ b/NewLife.Agent/WindowsService.cs @@ -313,15 +313,11 @@ public override unsafe Boolean IsRunning(String serviceName) } /// 安装服务 - /// 服务名 - /// - /// 文件路径 - /// 命令参数 - /// + /// 服务 /// - public override Boolean Install(String serviceName, String displayName, String fileName, String arguments, String description) + public override Boolean Install(ServiceModel service) { - XTrace.WriteLine("{0}.Install {1}, {2}, {3}, {4}", GetType().Name, serviceName, displayName, fileName, arguments, description); + XTrace.WriteLine("{0}.Install {1}, {2}, {3}, {4}", GetType().Name, service.ServiceName, service.DisplayName, service.FileName, service.Arguments, service.Description); if (!IsAdministrator()) return RunAsAdministrator("-i"); @@ -332,17 +328,17 @@ public override Boolean Install(String serviceName, String displayName, String f throw new Win32Exception(Marshal.GetLastWin32Error()); } - var binPath = fileName; - if (!arguments.IsNullOrEmpty()) binPath += " " + arguments; + var binPath = service.FileName; + if (!service.Arguments.IsNullOrEmpty()) binPath += " " + service.Arguments; - using var service = new SafeServiceHandle(CreateService(manager, serviceName, displayName, ServiceOptions.SERVICE_ALL_ACCESS, (Int32)ServiceType.Win32OwnProcess, (Int32)StartType.AutoStart, 1, binPath, null, 0, null, null, null)); - if (service.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); + using var handle = new SafeServiceHandle(CreateService(manager, service.ServiceName, service.DisplayName, ServiceOptions.SERVICE_ALL_ACCESS, (Int32)ServiceType.Win32OwnProcess, (Int32)StartType.AutoStart, 1, binPath, null, 0, null, null, null)); + if (handle.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); // 设置描述信息 - if (!description.IsNullOrEmpty()) + if (!service.Description.IsNullOrEmpty()) { SERVICE_DESCRIPTION sd; - sd.Description = Marshal.StringToHGlobalUni(description); + sd.Description = Marshal.StringToHGlobalUni(service.Description); var lpInfo = Marshal.AllocHGlobal(Marshal.SizeOf(sd)); try @@ -350,7 +346,7 @@ public override Boolean Install(String serviceName, String displayName, String f Marshal.StructureToPtr(sd, lpInfo, false); const Int32 SERVICE_CONFIG_DESCRIPTION = 1; - ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, lpInfo); + ChangeServiceConfig2(handle, SERVICE_CONFIG_DESCRIPTION, lpInfo); } finally { diff --git a/Test/Properties/launchSettings.json b/Test/Properties/launchSettings.json new file mode 100644 index 0000000..c9a0ca3 --- /dev/null +++ b/Test/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Test": { + "commandName": "Project", + "commandLineArgs": "-i -server http://s.newlifex.com:6600" + } + } +} \ No newline at end of file