用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 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

[[email protected] WebApp]$ systemc^C

[[email protected] 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,防火墙等等。

Writing a Linux daemon in C#

原文地址:https://www.cnblogs.com/xiaoliangge/p/8379992.html

时间: 2024-10-12 12:17:13

用C#编写Linux守护进程的相关文章

小何讲进程: 编写Linux守护进程方法详解

守护进程概述 守护进程,也就是通常所说的Daemon进程,是Linux中的后台服务进程. 它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些事件的发生. 守护进程常常在系统引导载入时启动,在系统关闭时终止. Linux有很多系统服务,大多数服务都是通过守护进程实现的.守护进程的名字通常以d结尾,字母d就是Daemon的意思. 由于在Linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端

Linux守护进程编写指南 (注:文章为转载)

*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin: 15px 0; } /* HEAD

【Linux学习】编写一个守护进程

题目: 编写一个守护进程,每隔3秒钟将当前时间输出.要求: 不能使用init_daemon系统调用. #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #include <unistd.h> int main(void) { pid_t pid; pid = fork(); if(pid > 0) { exit(0); } if(0 ==

Linux守护进程的编程实现

Linux 守护进程的编程方法 守护进程(Daemon)是执行在后台的一种特殊进程.它独立于控制终端而且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种非常实用的进程.Linux的大多数server就是用守护进程实现的.比方,Internetserverinetd,Webserverhttpd等.同一时候,守护进程完毕很多系统任务.比方,作业规划进程crond,打印进程lpd等. 守护进程的编程本身并不复杂,复杂的是各种版本号的Unix的实现机制不尽同样,造成不同Unix环境下守护进

笔记整理--Linux守护进程

Linux多进程开发(三)进程创建之守护进程的学习 - _Liang_Happy_Life__Dream - 51CTO技术博客 - Google Chrome (2013/10/11 16:48:27) Linux多进程开发(三)进程创建之守护进程的学习 2013-07-04 17:25:35 标签:守护进程 daemon Linux多进程开发 系统编程 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://liam2199.bl

[Linux] 守护进程和守护线程

对于JAVA而言,一般一个应用程序只有一个进程——JVM.除非在代码里面另外派生或者开启了新进程. 而线程,当然是由进程开启的.当开启该线程的进程离开时,线程也就不复存在了. 所以,对于JAVA而言,线程是完全可以由自己的API自由产生.例如new Thread().但是进程就不同,必须通过调用OS的API,如Runtime.getRuntime.exec(). 所以说,进程是OS级别的概念. 守护线程和用户线程的区别: 二者其实基本上是一样的.唯一的区别在于JVM何时离开. 用户线程:当存在任

转:linux守护进程的启动方法

Linux 守护进程的启动方法 作者: 阮一峰 日期: 2016年2月28日 "守护进程"(daemon)就是一直在后台运行的进程(daemon). 本文介绍如何将一个 Web 应用,启动为守护进程. 一.问题的由来 Web应用写好后,下一件事就是启动,让它一直在后台运行. 这并不容易.举例来说,下面是一个最简单的Node应用server.js,只有6行. var http = require('http'); http.createServer(function(req, res)

linux守护进程

#include <iostream>#include <unistd.h>//#include "curl/curl.h"#include "app_curl.h"#include "youtube_package.h"#include "CAutoMail.h"#include <fcntl.h>#include <signal.h>#include <unistd.h

C#开发Linux守护进程

C#开发Linux守护进程 Linux守护进程是Linux的后台服务进程,相当于Windows服务,对于为Linux开发服务程序的朋友来说,Linux守护进程相关技术是必不可少的,因为这个技术不仅仅是为了开发守护进程,还可以拓展到多进程,父子进程文件描述符共享,父子进程通讯.控制等方面,是实现Linux大型服务的基础技术之一. 去年我也曾写了一篇关于守护进程的帖子,名字叫<.NET跨平台实践:用C#开发Linux守护进程>,这篇文章的的确确实现了一个Daemon,不过,它有一个弱点,不能运行多