用C#编写Linux守护进程
如果要在Red Hat Enterprise Linux上將.NET Core進(jìn)程作為后臺(tái)進(jìn)程運(yùn)行,則可以創(chuàng)建自定義systemd單元。今天我將為.NET Core編寫(xiě)兩個(gè)自定義系統(tǒng)單元的例子。一個(gè)是運(yùn)行.NET Core控制臺(tái)應(yīng)用程序的一種類型,另一個(gè)是運(yùn)行ASP.NET Core Web應(yīng)用程序的簡(jiǎn)單類型。?
控制臺(tái)應(yīng)用程序
建立一個(gè)應(yīng)用程序
您可以用dotnet run在systemd中使用指定項(xiàng)目目錄作為工作目錄。但是,我們來(lái)構(gòu)建一個(gè)二進(jìn)制文件并將其用于systemd。用dotnet new 命令創(chuàng)建您的項(xiàng)目后編輯Program.cs如下。
using System;
using System.IO;
?
namespace ConsoleApplication
{
? ? public class Program
? ? {
? ? ? ? public static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? var path = Path.GetTempFileName();
? ? ? ? ? ? File.WriteAllText(path, "Hello Temp File!");
? ? ? ? ? ? Console.WriteLine($"Wrote temp file: {path}");
? ? ? ? }
? ? }
}
然后用dotnet publish命令發(fā)布項(xiàng)目。你會(huì)看到bin/<Configuration>/<Framework>目錄下的二進(jìn)制文件。
| $ dotnet publish -c ReleasePublishing ConsoleApp for .NETCoreApp,Version=v1.1Project ConsoleApp (.NETCoreApp,Version=v1.1) was previously compiled. Skipping compilation.publish: Published to /home/tatanaka/Documents/git/tanaka-takayoshi/SystemdExample/1.1/ConsoleApp/bin/Release/netcoreapp1.1/publishPublished 1/1 projects successfully |
創(chuàng)建一個(gè)自定義的systemd
首先,創(chuàng)建一個(gè)運(yùn)行守護(hù)進(jìn)程和工作目錄的用戶。
$ sudo useradd -s /sbin/nologin dotnetuser $ sudo mkdir /var/SystemdExample $ sudo cp /home/tatanaka/Documents/git/tanaka-takayoshi/SystemdExample/1.1/ConsoleApp/bin/Release/netcoreapp1.1/publish/* /var/SystemdExample $ sudo chown -R dotnetuser:dotnetuser /var/SystemdExample然后在/etc/systemd/system/目錄下創(chuàng)建一個(gè)自定義的systemd單元文件。文件名應(yīng)該是<unit-name>.<unit-type>。我創(chuàng)建的目錄和文件名為:/etc/systemd/system/netcore-console-example.service。
| [Unit]Description=Example for .NET Core ConsoleApp with systemdDefaultDependencies=no?[Service]Type=oneshotRemainAfterExit=noExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet ConsoleApp.dllWorkingDirectory=/var/SystemdExampleUser=dotnetuserGroup=dotnetuser??[install] |
您應(yīng)該在ExecStart中指定dotnet的完整路徑。以上是紅帽提供的.NET Core 1.1的情況。然后你可以用systemctl命令執(zhí)行守護(hù)進(jìn)程。您可以使用systemctl status命令或journalctl命令查看控制臺(tái)輸出。
| $ sudo systemctl start netcore-console-example.service$ sudo systemctl status netcore-console-example.service● netcore-console-example.service - Example for .NET Core ConsoleApp with systemd???Loaded: loaded (/etc/systemd/system/netcore-console-example.service; enabled; vendor preset: disabled)???Active: inactive (dead) since Fri 2017-02-24 00:29:16 JST; 13s ago??Process: 18075 ExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet ConsoleApp.dll (code=exited, status=0/SUCCESS)?Main PID: 18075 (code=exited, status=0/SUCCESS)?Feb 24 00:29:16 localhost.localdomain systemd[1]: Starting Example for .NET Core ConsoleApp with systemd...Feb 24 00:29:16 localhost.localdomain dotnet[18075]: Wrote temp file: /tmp/tmph1ok6H.tmpFeb 24 00:29:16 localhost.localdomain systemd[1]: Started Example for .NET Core ConsoleApp with systemd.?$ journalctl -u netcore-console-example.service -eFeb 24 00:29:16 localhost.localdomain systemd[1]: Starting Example for .NET Core ConsoleApp with systemd...Feb 24 00:29:16 localhost.localdomain dotnet[18075]: Wrote temp file: /tmp/tmph1ok6H.tmpFeb 24 00:29:16 localhost.localdomain systemd[1]: Started Example for .NET Core ConsoleApp with systemd.$ sudo cat /tmp/tmph1ok6H.tmpHello Temp File! |
使用PrivateTemp
在上述系統(tǒng)單元中,程序在臨時(shí)文件夾下寫(xiě)入一個(gè)文件。你有時(shí)想寫(xiě)一個(gè)來(lái)自其他用戶的臨時(shí)文件是安全的。您可以在[Service]section中的指定使用PrivateTemp。
| [Service]Type=oneshotRemainAfterExit=noExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet ConsoleApp.dllWorkingDirectory=/var/SystemdExampleUser=dotnetuserGroup=dotnetuserPrivateTemp=true |
?
重新加載單元文件后,程序可以以前一樣訪問(wèn)/tmp像目錄,但這不是實(shí)際的/tmp目錄。
| $ sudo systemctl daemon-reload $ sudo systemctl start netcore-console-example.service$ sudo systemctl status netcore-console-example.service● netcore-console-example.service - Example for .NET Core ConsoleApp with systemd???Loaded: loaded (/etc/systemd/system/netcore-console-example.service; enabled; vendor preset: disabled)???Active: inactive (dead) since Fri 2017-02-24 00:35:46 JST; 12s ago??Process: 18415 ExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet ConsoleApp.dll (code=exited, status=0/SUCCESS)?Main PID: 18415 (code=exited, status=0/SUCCESS)Feb 24 00:35:46 localhost.localdomain systemd[1]: Starting Example for .NET Core ConsoleApp with systemd...Feb 24 00:35:46 localhost.localdomain dotnet[18415]: Wrote temp file: /tmp/tmpJLWAGC.tmpFeb 24 00:35:46 localhost.localdomain systemd[1]: Started Example for .NET Core ConsoleApp with systemd.$ ls /tmp/tmpJLWAGC.tmpls: cannot access /tmp/tmpJLWAGC.tmp: No such file or directory |
Web應(yīng)用程序
建立一個(gè)應(yīng)用程序
現(xiàn)在我們來(lái)構(gòu)建一個(gè)ASP.NET Core Web應(yīng)用程序。今天我使用默認(rèn)的模板項(xiàng)目。
| $ dotnet new -t webCreated new C# project in /home/tatanaka/Documents/git/tanaka-takayoshi/SystemdExample/1.1/WebApp.$ dotnet restore ** snipped**log? : Restore completed in 9721ms.$ dotnet publish -c ReleasePublishing WebApp for .NETCoreApp,Version=v1.1** snipped **publish: Published to /home/tatanaka/Documents/git/tanaka-takayoshi/SystemdExample/1.1/WebApp/bin/Release/netcoreapp1.1/publishPublished 1/1 projects successfully |
現(xiàn)在可以用dotnet命令運(yùn)行。
| $ dotnet bin/Release/netcoreapp1.1/publish/WebApp.dll info: Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]??????User profile is available. Using '/home/tatanaka/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.Hosting environment: ProductionContent root path: /home/tatanaka/Documents/git/tanaka-takayoshi/SystemdExample/1.1/WebAppNow listening on: http://localhost:5000Application started. Press Ctrl+C to shut down. |
創(chuàng)建一個(gè)自定義的systemd
為這個(gè)Web應(yīng)用程序也指定dotnetuser名稱。
| $ sudo mkdir /var/SystemdExample$ sudo cp -R bin/Release/netcoreapp1.1/publish/* /var/SystemdWebExample$ sudo chown -R dotnetuser:dotnetuser /var/SystemdWebExample |
然后創(chuàng)建一個(gè)自定義的systemd單元文件/etc/systemd/system/netcore-web-example.service。
| [Unit]Description=Example for .NET Core WebApp with systemdDefaultDependencies=noWants=network.target # network is requiredAfter=network.target[Service]ExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet WebApp.dllWorkingDirectory=/var/SystemdWebExampleRestart=alwaysRestartSec=10?? # Restart service after 10 seconds if dotnet service crashesSyslogIdentifier=dotnet-exampleUser=dotnetuserGroup=dotnetuserPrivateTmp=trueEnvironment=ASPNETCORE_ENVIRONMENT=Production # specify environment variable for environmentEnvironment=ASPNETCORE_URLS=http://*:8080 # specify environement variable for listening port[Install]WantedBy = multi-user.target |
最后,您可以將ASP.NET Core應(yīng)用程序作為L(zhǎng)inux守護(hù)程序運(yùn)行。請(qǐng)注意,此應(yīng)用程序偵聽(tīng)端口8080代替了ASP.NET Core 默認(rèn)的 5000,因?yàn)槲以贏SPNETCORE_URLS單元文件中指定了環(huán)境變量??。
| $ systemctl start netcore-web-example.service[tatanaka@localhost WebApp]$ systemc^C[tatanaka@localhost WebApp]$ sudo systemctl status netcore-web-example.service[sudo] password for tatanaka: ● netcore-web-example.service - Example for .NET Core WebApp with systemd???Loaded: loaded (/etc/systemd/system/netcore-web-example.service; disabled; vendor preset: disabled)???Active: active (running) since Sat 2017-02-25 01:02:12 JST; 11s ago?Main PID: 7041 (dotnet)???CGroup: /system.slice/netcore-web-example.service???????????└─7041 /opt/rh/rh-dotnetcore11/root/usr/bin/dotnet WebApp.dllFeb 25 01:02:12 localhost.localdomain systemd[1]: Started Example for .NET Core WebApp with systemd.Feb 25 01:02:12 localhost.localdomain systemd[1]: Starting Example for .NET Core WebApp with systemd...Feb 25 01:02:12 localhost.localdomain dotnet-example[7041]: info: Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]Feb 25 01:02:12 localhost.localdomain dotnet-example[7041]: User profile is available. Using '/home/dotnetuser/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.Feb 25 01:02:13 localhost.localdomain dotnet-example[7041]: Hosting environment: ProductionFeb 25 01:02:13 localhost.localdomain dotnet-example[7041]: Content root path: /var/SystemdWebExampleFeb 25 01:02:13 localhost.localdomain dotnet-example[7041]: Now listening on: http://*:8080Feb 25 01:02:13 localhost.localdomain dotnet-example[7041]: Application started. Press Ctrl+C to shut down.$ journalctl -u netcore-web-example -xf-- Logs begin at Mon 2017-02-20 11:58:31 JST. --Feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]Feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: Sending file. Request path: '/images/banner4.svg'. Physical path: '/var/SystemdWebExample/wwwroot/images/banner4.svg'Feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]Feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: Request finished in 0.1973ms 200 image/svg+xmlFeb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]Feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: Request starting HTTP/1.1 GET http://localhost:8080/favicon.icoFeb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]Feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: Sending file. Request path: '/favicon.ico'. Physical path: '/var/SystemdWebExample/wwwroot/favicon.ico'Feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]Feb 25 01:02:36 localhost.localdomain dotnet-example[7041]: Request finished in 0.5824ms 200 image/x-icon |
然而這對(duì)于ASP.NET Core的生產(chǎn)使用來(lái)說(shuō)是不夠的。你可能需要設(shè)置一個(gè)反向代理服務(wù)器,比如Jexus,nginx,防火墻等等。
原文地址:http://www.cnblogs.com/xiaoliangge/p/8379992.html
.NET社區(qū)新聞,深度好文,歡迎訪問(wèn)公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的用C#编写Linux守护进程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 为什么选择.NETCore?
- 下一篇: 在Linux环境下使用Apache部署A