C#与Linux守护进程
用C#编写Linux守护进程

如果要在Red Hat Enterprise Linux上将.NET Core进程作为后台进程运行,则可以创建自定义systemd单元。今天我将为.NET Core编写两个自定义系统单元的例子。一个是运行.NET Core控制台应用程序的一种类型,另一个是运行ASP.NET Core Web应用程序的简单类型。
控制台应用程序
建立一个应用程序
您可以用dotnet run在systemd中使用指定项目目录作为工作目录。但是,我们来构建一个二进制文件并将其用于systemd。用dotnet new 命令创建您的项目后编辑Program.cs如下。

1 using System;
2 using System.IO;
3
4 namespace ConsoleApplication
5 {
6 public class Program
7 {
8 public static void Main(string[] args)
9 {
10 var path = Path.GetTempFileName();
11 File.WriteAllText(path, "Hello Temp File!");
12 Console.WriteLine($"Wrote temp file: {path}");
13 }
14 }
15 }

然后用dotnet publish命令发布项目。你会看到bin/<Configuration>/<Framework>目录下的二进制文件。
|
1
2
3
4
5
|
$ 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 |
创建一个自定义的systemd
首先,创建一个运行守护进程和工作目录的用户。
$ 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/目录下创建一个自定义的systemd单元文件。文件名应该是<unit-name>.<unit-type>。我创建的目录和文件名为:/etc/systemd/system/netcore-console-example.service。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[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] |
您应该在ExecStart中指定dotnet的完整路径。以上是红帽提供的.NET Core 1.1的情况。然后你可以用systemctl命令执行守护进程。您可以使用systemctl status命令或journalctl命令查看控制台输出。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
$ 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
在上述系统单元中,程序在临时文件夹下写入一个文件。你有时想写一个来自其他用户的临时文件是安全的。您可以在[Service]section中的指定使用PrivateTemp。
|
1
2
3
4
5
6
7
8
|
[Service]Type=oneshotRemainAfterExit=noExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet ConsoleApp.dllWorkingDirectory=/var/SystemdExampleUser=dotnetuserGroup=dotnetuserPrivateTemp=true |
重新加载单元文件后,程序可以像前一样访问/tmp目录,但这不是实际的/tmp目录。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
$ 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应用程序
建立一个应用程序
现在我们来构建一个ASP.NET Core Web应用程序。今天我使用默认的模板项目。
|
1
2
3
4
5
6
7
8
9
10
|
$ 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 |
现在可以用dotnet命令运行。
|
1
2
3
4
5
6
7
|
$ 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. |
创建一个自定义的systemd
为这个Web应用程序也指定dotnetuser名称。
|
1
2
3
|
$ sudo mkdir /var/SystemdExample$ sudo cp -R bin/Release/netcoreapp1.1/publish/* /var/SystemdWebExample$ sudo chown -R dotnetuser:dotnetuser /var/SystemdWebExample |
然后创建一个自定义的systemd单元文件/etc/systemd/system/netcore-web-example.service。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
[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应用程序作为Linux守护程序运行。请注意,此应用程序侦听端口8080代替了ASP.NET Core 默认的 5000,因为我在ASPNETCORE_URLS单元文件中指定了环境变量 。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
$ 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 |
然而这对于ASP.NET Core的生产使用来说是不够的。你可能需要设置一个反向代理服务器,比如Jexus,nginx,防火墙等等。
C#与Linux守护进程的更多相关文章
- .NET跨平台实践:用C#开发Linux守护进程
Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...
- .NET跨平台实践:用C#开发Linux守护进程(转)
Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...
- [转]❲阮一峰❳Linux 守护进程的启动方法
❲阮一峰❳Linux 守护进程的启动方法 "守护进程"(daemon)就是一直在后台运行的进程(daemon). 本文介绍如何将一个 Web 应用,启动为守护进程. 一.问题的由来 ...
- Server Develop (七) Linux 守护进程
守护进程 守护进程,也就是通常说的Daemon进程,是Linux中的后台服务进程.它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程常常在系统引导装 ...
- Linux 守护进程和超级守护进程(xinetd)
一 .Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程来执行的 ...
- Linux守护进程详解(init.d和xinetd) [转]
一 Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台 的守护进程来执行的 ...
- Linux守护进程的编程实现
Linux 守护进程的编程方法 守护进程(Daemon)是执行在后台的一种特殊进程.它独立于控制终端而且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种非常实用的进程.Linux的大多数s ...
- Linux守护进程详解(init.d和xinetd)
一 Linux守护进程 Linux 服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程来执行的. ...
- C#开发Linux守护进程
用C#开发Linux守护进程 Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon ...
- 笔记整理--Linux守护进程
Linux多进程开发(三)进程创建之守护进程的学习 - _Liang_Happy_Life__Dream - 51CTO技术博客 - Google Chrome (2013/10/11 16:48:2 ...
随机推荐
- 空值(NULL)和非空(NOT NULL)(十二)
不多说,直接上干货! NULL:表示字段可以为空 NOT NULL:表示字段不允许为空 注意:NULL和NOT NULL不可以同时用于一个字段上. create table tb2( username ...
- OLTP 与 OLAP
OLTP:On-Line Transaction Processing(联机事务处理过程).也称为面向交易的处理过程,其基本特征是前台接收的用户数据可以立即传送到计算中心进行处理,并在很短的时间内给出 ...
- core组件进阶
访问图像像素 存储方式 BGR连续存储有助于提升图像扫描速度. isContinuous()判断是否是连续存储. 颜色空间缩减 仅用这些颜色中具有代表性的很小的部分,就足以达到同样的效果. 将现有颜色 ...
- python 自动广播机制 (broadcasting)
一定要注意,执行 broadcast 的前提在于,两个 ndarray 执行的是 element-wise(按位加,按位减) 的运算,而不是矩阵乘法的运算,矩阵乘法运算时需要维度之间严格匹配.(且矩阵 ...
- [NOIP2014普及组]子矩阵
题目:洛谷P2258.Vijos P1914.codevs 3904. 题目大意:给你一个矩阵,要你找一个r行c列的子矩阵,求最小分值(子矩阵和分值的定义见原题). 解题思路:n和m比较小,考虑暴力. ...
- 洛谷P1006 传纸条 (棋盘dp)
好气,在洛谷上交就过了,在caioj上交就只有40分 之前在51nod做过这道题了. https://blog.csdn.net/qq_34416123/article/details/8180902 ...
- C# 从需要登录的网站上抓取数据
[转] C# 从需要登录的网站上抓取数据 背景:昨天一个学金融的同学让我帮她从一个网站上抓取数据,然后导出到excel,粗略看了下有1000+条记录,人工统计的话确实不可能.虽说不会,但作为一个学计算 ...
- HDFS文件系统上传时序图 PB级文件存储时序图
自己设计的时序图. 来自为知笔记(Wiz)
- HDU3265 Examining the Rooms【stirling数】
题目链接: http://acm.hdu.edu.cn/showproblem.php? pid=3625 题目大意: 有N个房间,每一个房间的要是随机放在某个房间内,概率同样.有K次炸门的机会. 求 ...
- CoAP与物联网系统
CoAP简单介绍 引自维基百科上的介绍,用的是谷歌翻译... 受约束的应用协议(COAP)是一种软件协议旨在以很easy的电子设备.使他们能够在互联网上进行交互式通信中使用. 它特别针对小型低功率传感 ...