用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如下。
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
命令发布项目。你会看到bin/<Configuration>/<Framework>目录下的二进制文件
。
1
2
3
4
5
|
$ dotnet publish -c Release Publishing ConsoleApp for .NETCoreApp,Version=v1.1 Project 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/publish Published 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 systemd DefaultDependencies=no [Service] Type=oneshot RemainAfterExit=no ExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet ConsoleApp.dll WorkingDirectory=/var/SystemdExample User=dotnetuser Group=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.tmp Feb 24 00:29:16 localhost.localdomain systemd[1]: Started Example for .NET Core ConsoleApp with systemd. $ journalctl -u netcore-console-example.service -e 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.tmp Feb 24 00:29:16 localhost.localdomain systemd[1]: Started Example for .NET Core ConsoleApp with systemd. $ sudo cat /tmp/tmph1ok6H.tmp Hello Temp File! |
使用PrivateTemp
在上述系统单元中,程序在临时文件夹下写入一个文件。你有时想写一个来自其他用户的临时文件是安全的。您可以在[Service]
section中的指定使用PrivateTemp。
1
2
3
4
5
6
7
8
|
[Service] Type=oneshot RemainAfterExit=no ExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet ConsoleApp.dll WorkingDirectory=/var/SystemdExample User=dotnetuser Group=dotnetuser PrivateTemp=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.tmp Feb 24 00:35:46 localhost.localdomain systemd[1]: Started Example for .NET Core ConsoleApp with systemd. $ ls /tmp/tmpJLWAGC.tmp ls: 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 web Created 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 Release Publishing WebApp for .NETCoreApp,Version=v1.1 ** snipped ** publish: Published to /home/tatanaka/Documents/git/tanaka-takayoshi/SystemdExample/1.1/WebApp/bin/Release/netcoreapp1.1/publish Published 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: Production Content root path: /home/tatanaka/Documents/git/tanaka-takayoshi/SystemdExample/1.1/WebApp Now listening on: http://localhost:5000 Application 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 systemd DefaultDependencies=no Wants=network.target # network is required After=network.target [Service] ExecStart=/opt/rh/rh-dotnetcore11/root/usr/bin/dotnet WebApp.dll WorkingDirectory=/var/SystemdWebExample Restart=always RestartSec=10 # Restart service after 10 seconds if dotnet service crashes SyslogIdentifier=dotnet-example User=dotnetuser Group=dotnetuser PrivateTmp=true Environment=ASPNETCORE_ENVIRONMENT=Production # specify environment variable for environment Environment=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.dll Feb 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: Production Feb 25 01:02:13 localhost.localdomain dotnet-example[7041]: Content root path: /var/SystemdWebExample Feb 25 01:02:13 localhost.localdomain dotnet-example[7041]: Now listening on: http://*:8080 Feb 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+xml Feb 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.ico 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: '/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守护进程的更多相关文章
- C#与Linux守护进程
用C#编写Linux守护进程 如果要在Red Hat Enterprise Linux上将.NET Core进程作为后台进程运行,则可以创建自定义systemd单元.今天我将为.NET Core编 ...
- Linux守护进程编写指南
Linux守护进程编写指南 守护进程(Daemon)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种很有用的进 程.Linux的大多数服务器 ...
- Linux守护进程的编程实现
Linux 守护进程的编程方法 守护进程(Daemon)是执行在后台的一种特殊进程.它独立于控制终端而且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种非常实用的进程.Linux的大多数s ...
- 笔记整理--Linux守护进程
Linux多进程开发(三)进程创建之守护进程的学习 - _Liang_Happy_Life__Dream - 51CTO技术博客 - Google Chrome (2013/10/11 16:48:2 ...
- CentOS 7.4 初次手记:第一章 Linux守护进程(daemon)
第一节 init & sysvinit 6 I sysvinit 运行顺序... 6 II Sysvinit和系统关闭... 7 III Sysvinit 的小结... 7 IV 运行级别.. ...
- 【转】学习Linux守护进程详细笔记
[原文]https://www.toutiao.com/i6566814959966093837/ Linux守护进程 一. 守护进程概述 守护进程,也就是通常所说的Daemon进程,是Linux中的 ...
- [Linux] 守护进程和守护线程
对于JAVA而言,一般一个应用程序只有一个进程——JVM.除非在代码里面另外派生或者开启了新进程. 而线程,当然是由进程开启的.当开启该线程的进程离开时,线程也就不复存在了. 所以,对于JAVA而言, ...
- .NET跨平台实践:用C#开发Linux守护进程
Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...
- .NET跨平台实践:用C#开发Linux守护进程(转)
Linux守护进程(Daemon)是Linux的后台服务进程,它脱离了与控制终端的关联,直接由Linux init进程管理其生命周期,即使你关闭了控制台,daemon也能在后台正常工作. 一句话,为L ...
随机推荐
- J2EE 项目 org.apache.jasper.JasperException: 解决方法
项目从一个电脑转移到另一台电脑总是有各种意外qaq~ 刚放假把从实验室的项目拷回自己的电脑回家继续coding,结果出了这个错误.... 各个地方都调试原来是Tomcat版本问题!!!我电脑上的是6. ...
- 20 Zabbix系统性能优化建议
点击返回:自学Zabbix之路 20 Zabbix系统性能优化建议 1. Zabbix性能变慢的可能表现: zabbix队列有太多被延迟的item,可以通过administration-queue查看 ...
- 【Manacher算法】求最长回文串的优秀算法
先贴一下代码~ //by 减维 #include<cstdio> #include<iostream> #include<cstring> #include< ...
- Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现
2017年4月29日~5月1日,国际劳动节, 三天的小长假. 在国内,小长假往往是这样的: 然而我当时在戏称为"德村"(德国农村)的Walldorf出差并且住在Wiesloch, ...
- linked lists in .NET
链表是数据结构中存储数据的一种形式.分为单向链表和双向链表以及循环链表.LinkedList是泛型链表,用节点存取,节点类型为LinkedListNode<T>,每个节点都有Next和Pr ...
- Beyond Globally Optimal: Focused Learning
这里对WWW 2017文章<Beyond Globally Optimal: Focused Learning for Improved Recommendations>进行一个简单的分析 ...
- 【JavaScript 实现倒计时(天、时、分、秒)】
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- Java集合源码分析(三)Vevtor和Stack
前言 前面写了一篇关于的是LinkedList的除了它的数据结构稍微有一点复杂之外,其他的都很好理解的.这一篇讲的可能大家在开发中很少去用到.但是有的时候也可能是会用到的! 注意在学习这一篇之前,需要 ...
- 【批处理学习笔记】第十四课:常用DOS命令(4)
系统管理at 安排在特定日期和时间运行命令和程序shutdown立即或定时关机或重启taskkill结束进程(WinXPHome版中无该命令)tasklist显示进程列表(Windows XP Hom ...
- 【批处理学习笔记】第十一课:常用DOS命令(1)
[ 文件夹管理 ]cd 显示当前目录名或改变当前目录.md 创建目录.rd 删除一个目录.dir 显示目录中的文件和子目录列表.tree 以图形显示驱动器或路径的文件夹结构.path 为可执行文件显示 ...