When writing programs, you will inevitably encounter the need to make system services. Windows write down system services need to implement some specific interfaces, which is difficult to do, so many programs adopt a similar alternative - to make desktop applications with system taskbar icons. However, the reason why a service is a service is that it has a very important feature: it can be started automatically without user login. Otherwise, how hard it is to log in manually every time you restart. Of course, windows can set up automatic login, but if it is a managed server, are you sure you can log in automatically?
Linux seems to be much more convenient. Programs that do not need GUI to run continuously can be made into services.
1. Service in Windows
Let's start with windows. If you're still using Windows XP, let's say goodbye
1.1. Windows Service Wrapper
[Windows Service Wrapper] is the full name. Its abbreviation WinSW may be more famous.
WinSW is implemented based on. NET Framework 4.6.1 and. NET 5, so it requires at least Windows 7 SP1 / Windows Server 2008 R2 SP1 to be used. It can encapsulate any windows program into a Windows service. All you need to do is write a configuration file, and then register a Windows service with WinSW. WinSW Download The following is an independent executable file. Before use, you need to write a configuration file with the same name as the executable file name but the extension is. xml and put it in the same directory.
For example, nginx itself does not provide the ability to register as a Windows service. If you need to register as a Windows service, you can use WinSW to encapsulate it. Change the downloaded WinSW executable file to winsw.exe (any name is OK, and the configuration file name can be created according to the same name) and put it under the main directory of nginx. The directory structure after creating the configuration file is roughly as follows:
[-] nginx |-- conf |-- ...(other nginx Directory or file) |-- nginx.exe |-- winsw.exe `-- winsw.xml
The configuration content in winsw.xml is as follows. You can understand it by looking at the comments.
<service> <!-- Configure service name nginx-service,Display name Nginx Service,And service description --> <id>nginx-service</id> <name>Nginx Service</name> <description>Nginx Service</description> <!-- The working directory where the service runs. Give the absolute path --> <workingdirectory>C:\Local\Nginx</workingdirectory> <!-- Service executable, give absolute path --> <executable>C:\Local\Nginx\nginx.exe</executable> <!-- Executable to stop the service --> <stopexecutable>C:\Local\Nginx\nginx.exe</stopexecutable> <!-- Parameters to stop the service --> <stoparguments>-s stop</stoparguments> <priority>Normal</priority> <stoptimeout>15 sec</stoptimeout> <stopparentprocessfirst>false</stopparentprocessfirst> <!-- The configuration service type is「automatic」start-up --> <startmode>Automatic</startmode> <waithint>15 sec</waithint> <sleeptime>1 sec</sleeptime> <!-- Console output of the service (standard output)/Error (output) write log --> <!-- among %BASE% Means winsw.exe Directory --> <!-- reference resources: https://github.com/winsw/winsw/blob/master/doc/loggingAndErrorReporting.md --> <logpath>%BASE%\logs</logpath> <log mode="roll-by-time"> <pattern>yyyyMMdd</pattern> </log> </service>
This configuration creates a Windows Service named Nginx Service, which is displayed as Nginx Service in "services (services.msc)" of windows. When starting the service, run nginx.exe directly to start it. This is a program that will occupy the console; To stop the service, run nginx.exe -s stop. The executable program and parameters are configured in < stopexecutable > and < stoparguments > respectively - it is not difficult to infer that if parameters are required to start the service, they are configured in < arguments >.
The detailed configuration can be found in the github library XML configuratoin file You can also find some in Example.
After configuration, run winsw.exe install to install as a Windows service. After installation, you can use the winsw.exe start command to start the service, go to the windows service manager to start it, or use the net start command to start it. github Library Usage section of the home page There is a complete command description.
1.2. Write one by yourself with. NET Framework/Core/5
It is easy to write a service with. NET because there are ready-made packages (components) that can be used: NuGet Gallery | Microsoft.Extensions.Hosting.WindowsServices , official. It needs to rely on at least two packages:
- NuGet Gallery | Microsoft.Extensions.Hosting
- NuGet Gallery | Microsoft.Extensions.Hosting.Abstractions
After introducing components, only a small amount of code is needed to make the current. NET Console Application a service program that supports Windows service interface.
// Program.cs class Program { static async Task<int> Main(string[] args) { await CreateHostBuilder(args).Build().RunAsync(); } public static IHostBuilder CreateHostBuilder(string[] args) { return Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddHostedService<DaemonService>(); }) .UseWindowsService(); } }
Note that addhostedservice < daemonservice >, where daemonservice is a self implemented service business class, which is freely named, but needs to inherit from Microsoft.Extensions.Hosting.BackgroundService
class DaemonService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { // TODO provides the code of service content } }
The business code of a service is usually running or listening code. If it is a planned / periodic task, you can consider using it Quartz To achieve.
After the program is completed, you can use the sc command provided by Windows to register / unregister the service. Assuming that the generated program is MyService.exe, the commands for registering, configuring and starting services are as follows:
sc create "my-service" binPath="C:\MyService\MyService.exe --service" sc config "my-service" start= auto sc start "my-service"
Note: absolute path should be given in binPath.
2. System D service in Ubuntu
There are many kinds of services under Linux. Recently, we mainly use Ubuntu, so we do system D services under Ubuntu.
Suppose we write an ASP.NET application of. NET 5 and put it in / APP / my Web /, and the main file is MyWeb.dll. If you start this Web from the command line, it should be
cd /app/my-web dotnet MyWeb.dll
Note: the operating environment of. NET 5 needs to be prepared in advance. Please refer to Install. Net -. Net | Microsoft docs on Ubuntu.
Next, write the system D service configuration. The configuration file is named my-web.service and placed in the / etc/systemd/system directory. The contents (including notes) are as follows:
[Unit] # Service description Description=My Web Application # Start after starting the network service After=network.target [Service] # Always restart (restart immediately after ending for any reason) Restart=always RestartSec=10 # working directory WorkingDirectory=/app/my-web # Command to start the service ExecStart=/usr/bin/dotnet MyWeb.dll # End the service by killing the master process ExecStop=/bin/kill -HUP $MAINPID TimeoutStopSec=5 KillMode=mixed SyslogIdentifier=my-web # Specifying the user running this service involves issues such as directory access rights User=james [Install] WantedBy=multi-user.target
The service cannot be started immediately after configuration. You need systemd to reload the configuration before starting the service:
sudo systemctl daemon-reload sudo systemctl start my-web
By the way, if you want to restart automatically after content publishing, you need to add two configuration files, one. path to monitor changes and one. service to restart my web:
- restart-my-web.path
[Path] # Monitor the change of the main file MyWeb.dll. If there is any change, restart-my-web.service will be triggered PathModified=/app/my-web/MyWeb.dll [Install] WantedBy=multi-user.target
- restart-my-web.service
[Unit] Description=My Web Restarter After=network.target [Service] Type=oneshot # Anti shake, only start once in 60 seconds ExecStartPre=/bin/sleep 60 # Restart my-web.service ExecStart=/bin/systemctl restart my-web.service [Install] WantedBy=multi-user.target
3. A little summary
It is not difficult to provide services. The only way to write code is to implement components out of the box. But then again, it's not difficult to do service. There are still many things to consider in the design of service. such as
- How to monitor service status—— Process monitoring, heartbeat check
- How to analyze errors in services—— system log
- How to provide a GUI to manage services—— The Web or other UI interacts with the service process (process communication, Management API, etc.)
- ......
Since it's not difficult to do service, don't worry too much about how to "do" (provide) service, but more about how to do (Design) service well.